{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Ecommerce: reverse image search\n",
    "\n",
    "All e-commerce platforms need a search mechanism. The built-in methods usually rely on some variation of full-text search which finds the relevant documents based on the presence of the words used in a query. In some cases, it might be enough, but there are ways to improve that mechanism and increase sales. If your customer can easily find a product they need, they are more likely to buy it.\n",
    "\n",
    "Semantic search is one of the possibilities. It relies not only on keywords but considers the meaning and intention of the query. However, reverse image search might be a way to go if you want to enable non-textual search capabilities. Your customers may struggle to express themselves, so why don't you ease that and start accepting images as your search queries?\n",
    "\n",
    "# Amazon product dataset 2020\n",
    "\n",
    "We will use the [Amazon product dataset 2020](https://www.kaggle.com/datasets/promptcloud/amazon-product-dataset-2020/) and see how to enable visual queries for it. The following lines will download it from the cloud and create a directory structure so you can reproduce the results independently."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:08:43.494319Z",
     "start_time": "2023-07-20T09:08:42.607368Z"
    },
    "is_executing": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "mkdir: cannot create directory ‘data’: File exists\n",
      "mkdir: cannot create directory ‘data/images’: File exists\n",
      "mkdir: cannot create directory ‘queries’: File exists\n",
      "File ‘data/amazon-product-dataset-2020.zip’ already there; not retrieving.\n",
      "\n",
      "File ‘queries/ecommerce-reverse-image-search-queries.zip’ already there; not retrieving.\n",
      "\n",
      "Archive:  queries/ecommerce-reverse-image-search-queries.zip\n"
     ]
    }
   ],
   "source": [
    "!mkdir data\n",
    "!mkdir data/images\n",
    "!mkdir queries\n",
    "!wget -nc --directory-prefix=data/ \"https://storage.googleapis.com/qdrant-examples/amazon-product-dataset-2020.zip\"\n",
    "!wget -nc --directory-prefix=queries/ \"https://storage.googleapis.com/qdrant-examples/ecommerce-reverse-image-search-queries.zip\"\n",
    "!unzip -u -d queries queries/ecommerce-reverse-image-search-queries.zip"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:08:47.779869Z",
     "start_time": "2023-07-20T09:08:43.503915Z"
    },
    "is_executing": true,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Defaulting to user installation because normal site-packages is not writeable\n",
      "Requirement already satisfied: jupyter in /home/user/.local/lib/python3.10/site-packages (1.0.0)\n",
      "Requirement already satisfied: pandas in /home/user/.local/lib/python3.10/site-packages (2.0.3)\n",
      "Requirement already satisfied: sentence_transformers in /home/user/.local/lib/python3.10/site-packages (2.2.2)\n",
      "Requirement already satisfied: qdrant_client~=1.3.0 in /home/user/.local/lib/python3.10/site-packages (1.3.1)\n",
      "Requirement already satisfied: pyarrow in /home/user/.local/lib/python3.10/site-packages (12.0.1)\n",
      "Requirement already satisfied: notebook in /home/user/.local/lib/python3.10/site-packages (from jupyter) (6.5.4)\n",
      "Requirement already satisfied: jupyter-console in /home/user/.local/lib/python3.10/site-packages (from jupyter) (6.6.3)\n",
      "Requirement already satisfied: nbconvert in /home/user/.local/lib/python3.10/site-packages (from jupyter) (7.6.0)\n",
      "Requirement already satisfied: ipywidgets in /home/user/.local/lib/python3.10/site-packages (from jupyter) (8.0.6)\n",
      "Requirement already satisfied: qtconsole in /home/user/.local/lib/python3.10/site-packages (from jupyter) (5.4.3)\n",
      "Requirement already satisfied: ipykernel in /home/user/.local/lib/python3.10/site-packages (from jupyter) (6.23.3)\n",
      "Requirement already satisfied: python-dateutil>=2.8.2 in /home/user/.local/lib/python3.10/site-packages (from pandas) (2.8.2)\n",
      "Requirement already satisfied: tzdata>=2022.1 in /home/user/.local/lib/python3.10/site-packages (from pandas) (2023.3)\n",
      "Requirement already satisfied: pytz>=2020.1 in /usr/lib/python3/dist-packages (from pandas) (2022.1)\n",
      "Requirement already satisfied: numpy>=1.21.0 in /home/user/.local/lib/python3.10/site-packages (from pandas) (1.25.0)\n",
      "Requirement already satisfied: nltk in /home/user/.local/lib/python3.10/site-packages (from sentence_transformers) (3.8.1)\n",
      "Requirement already satisfied: tqdm in /home/user/.local/lib/python3.10/site-packages (from sentence_transformers) (4.65.0)\n",
      "Requirement already satisfied: torch>=1.6.0 in /home/user/.local/lib/python3.10/site-packages (from sentence_transformers) (2.0.1)\n",
      "Requirement already satisfied: sentencepiece in /home/user/.local/lib/python3.10/site-packages (from sentence_transformers) (0.1.99)\n",
      "Requirement already satisfied: huggingface-hub>=0.4.0 in /home/user/.local/lib/python3.10/site-packages (from sentence_transformers) (0.15.1)\n",
      "Requirement already satisfied: transformers<5.0.0,>=4.6.0 in /home/user/.local/lib/python3.10/site-packages (from sentence_transformers) (4.30.2)\n",
      "Requirement already satisfied: scipy in /home/user/.local/lib/python3.10/site-packages (from sentence_transformers) (1.11.1)\n",
      "Requirement already satisfied: scikit-learn in /home/user/.local/lib/python3.10/site-packages (from sentence_transformers) (1.2.2)\n",
      "Requirement already satisfied: torchvision in /home/user/.local/lib/python3.10/site-packages (from sentence_transformers) (0.15.2)\n",
      "Requirement already satisfied: typing-extensions<4.6.0,>=4.0.0 in /home/user/.local/lib/python3.10/site-packages (from qdrant_client~=1.3.0) (4.5.0)\n",
      "Requirement already satisfied: grpcio>=1.41.0 in /home/user/.local/lib/python3.10/site-packages (from qdrant_client~=1.3.0) (1.56.0)\n",
      "Requirement already satisfied: pydantic<2.0,>=1.8 in /home/user/.local/lib/python3.10/site-packages (from qdrant_client~=1.3.0) (1.10.9)\n",
      "Requirement already satisfied: portalocker<3.0.0,>=2.7.0 in /home/user/.local/lib/python3.10/site-packages (from qdrant_client~=1.3.0) (2.7.0)\n",
      "Requirement already satisfied: httpx[http2]>=0.14.0 in /home/user/.local/lib/python3.10/site-packages (from qdrant_client~=1.3.0) (0.24.1)\n",
      "Requirement already satisfied: urllib3<2.0.0,>=1.26.14 in /home/user/.local/lib/python3.10/site-packages (from qdrant_client~=1.3.0) (1.26.16)\n",
      "Requirement already satisfied: grpcio-tools>=1.41.0 in /home/user/.local/lib/python3.10/site-packages (from qdrant_client~=1.3.0) (1.56.0)\n",
      "Requirement already satisfied: setuptools in /home/user/.local/lib/python3.10/site-packages (from grpcio-tools>=1.41.0->qdrant_client~=1.3.0) (66.0.0)\n",
      "Requirement already satisfied: protobuf<5.0dev,>=4.21.6 in /home/user/.local/lib/python3.10/site-packages (from grpcio-tools>=1.41.0->qdrant_client~=1.3.0) (4.23.3)\n",
      "Requirement already satisfied: certifi in /usr/lib/python3/dist-packages (from httpx[http2]>=0.14.0->qdrant_client~=1.3.0) (2020.6.20)\n",
      "Requirement already satisfied: httpcore<0.18.0,>=0.15.0 in /home/user/.local/lib/python3.10/site-packages (from httpx[http2]>=0.14.0->qdrant_client~=1.3.0) (0.17.2)\n",
      "Requirement already satisfied: idna in /usr/lib/python3/dist-packages (from httpx[http2]>=0.14.0->qdrant_client~=1.3.0) (3.3)\n",
      "Requirement already satisfied: sniffio in /home/user/.local/lib/python3.10/site-packages (from httpx[http2]>=0.14.0->qdrant_client~=1.3.0) (1.3.0)\n",
      "Requirement already satisfied: h2<5,>=3 in /home/user/.local/lib/python3.10/site-packages (from httpx[http2]>=0.14.0->qdrant_client~=1.3.0) (4.1.0)\n",
      "Requirement already satisfied: fsspec in /home/user/.local/lib/python3.10/site-packages (from huggingface-hub>=0.4.0->sentence_transformers) (2023.6.0)\n",
      "Requirement already satisfied: pyyaml>=5.1 in /usr/lib/python3/dist-packages (from huggingface-hub>=0.4.0->sentence_transformers) (5.4.1)\n",
      "Requirement already satisfied: requests in /usr/lib/python3/dist-packages (from huggingface-hub>=0.4.0->sentence_transformers) (2.25.1)\n",
      "Requirement already satisfied: packaging>=20.9 in /usr/lib/python3/dist-packages (from huggingface-hub>=0.4.0->sentence_transformers) (21.3)\n",
      "Requirement already satisfied: filelock in /home/user/.local/lib/python3.10/site-packages (from huggingface-hub>=0.4.0->sentence_transformers) (3.9.0)\n",
      "Requirement already satisfied: six>=1.5 in /usr/lib/python3/dist-packages (from python-dateutil>=2.8.2->pandas) (1.16.0)\n",
      "Requirement already satisfied: triton==2.0.0 in /home/user/.local/lib/python3.10/site-packages (from torch>=1.6.0->sentence_transformers) (2.0.0)\n",
      "Requirement already satisfied: nvidia-cuda-nvrtc-cu11==11.7.99 in /home/user/.local/lib/python3.10/site-packages (from torch>=1.6.0->sentence_transformers) (11.7.99)\n",
      "Requirement already satisfied: nvidia-nvtx-cu11==11.7.91 in /home/user/.local/lib/python3.10/site-packages (from torch>=1.6.0->sentence_transformers) (11.7.91)\n",
      "Requirement already satisfied: nvidia-cublas-cu11==11.10.3.66 in /home/user/.local/lib/python3.10/site-packages (from torch>=1.6.0->sentence_transformers) (11.10.3.66)\n",
      "Requirement already satisfied: nvidia-cusparse-cu11==11.7.4.91 in /home/user/.local/lib/python3.10/site-packages (from torch>=1.6.0->sentence_transformers) (11.7.4.91)\n",
      "Requirement already satisfied: nvidia-cuda-cupti-cu11==11.7.101 in /home/user/.local/lib/python3.10/site-packages (from torch>=1.6.0->sentence_transformers) (11.7.101)\n",
      "Requirement already satisfied: nvidia-cusolver-cu11==11.4.0.1 in /home/user/.local/lib/python3.10/site-packages (from torch>=1.6.0->sentence_transformers) (11.4.0.1)\n",
      "Requirement already satisfied: nvidia-cufft-cu11==10.9.0.58 in /home/user/.local/lib/python3.10/site-packages (from torch>=1.6.0->sentence_transformers) (10.9.0.58)\n",
      "Requirement already satisfied: nvidia-nccl-cu11==2.14.3 in /home/user/.local/lib/python3.10/site-packages (from torch>=1.6.0->sentence_transformers) (2.14.3)\n",
      "Requirement already satisfied: nvidia-cudnn-cu11==8.5.0.96 in /home/user/.local/lib/python3.10/site-packages (from torch>=1.6.0->sentence_transformers) (8.5.0.96)\n",
      "Requirement already satisfied: jinja2 in /home/user/.local/lib/python3.10/site-packages (from torch>=1.6.0->sentence_transformers) (3.1.2)\n",
      "Requirement already satisfied: nvidia-curand-cu11==10.2.10.91 in /home/user/.local/lib/python3.10/site-packages (from torch>=1.6.0->sentence_transformers) (10.2.10.91)\n",
      "Requirement already satisfied: sympy in /home/user/.local/lib/python3.10/site-packages (from torch>=1.6.0->sentence_transformers) (1.12)\n",
      "Requirement already satisfied: nvidia-cuda-runtime-cu11==11.7.99 in /home/user/.local/lib/python3.10/site-packages (from torch>=1.6.0->sentence_transformers) (11.7.99)\n",
      "Requirement already satisfied: networkx in /home/user/.local/lib/python3.10/site-packages (from torch>=1.6.0->sentence_transformers) (3.1)\n",
      "Requirement already satisfied: wheel in /home/user/.local/lib/python3.10/site-packages (from nvidia-cublas-cu11==11.10.3.66->torch>=1.6.0->sentence_transformers) (0.38.4)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: lit in /home/user/.local/lib/python3.10/site-packages (from triton==2.0.0->torch>=1.6.0->sentence_transformers) (16.0.6)\n",
      "Requirement already satisfied: cmake in /home/user/.local/lib/python3.10/site-packages (from triton==2.0.0->torch>=1.6.0->sentence_transformers) (3.26.4)\n",
      "Requirement already satisfied: regex!=2019.12.17 in /home/user/.local/lib/python3.10/site-packages (from transformers<5.0.0,>=4.6.0->sentence_transformers) (2023.6.3)\n",
      "Requirement already satisfied: tokenizers!=0.11.3,<0.14,>=0.11.1 in /home/user/.local/lib/python3.10/site-packages (from transformers<5.0.0,>=4.6.0->sentence_transformers) (0.13.3)\n",
      "Requirement already satisfied: safetensors>=0.3.1 in /home/user/.local/lib/python3.10/site-packages (from transformers<5.0.0,>=4.6.0->sentence_transformers) (0.3.1)\n",
      "Requirement already satisfied: comm>=0.1.1 in /home/user/.local/lib/python3.10/site-packages (from ipykernel->jupyter) (0.1.3)\n",
      "Requirement already satisfied: debugpy>=1.6.5 in /home/user/.local/lib/python3.10/site-packages (from ipykernel->jupyter) (1.6.7)\n",
      "Requirement already satisfied: matplotlib-inline>=0.1 in /home/user/.local/lib/python3.10/site-packages (from ipykernel->jupyter) (0.1.6)\n",
      "Requirement already satisfied: pyzmq>=20 in /home/user/.local/lib/python3.10/site-packages (from ipykernel->jupyter) (25.1.0)\n",
      "Requirement already satisfied: jupyter-client>=6.1.12 in /home/user/.local/lib/python3.10/site-packages (from ipykernel->jupyter) (8.3.0)\n",
      "Requirement already satisfied: traitlets>=5.4.0 in /home/user/.local/lib/python3.10/site-packages (from ipykernel->jupyter) (5.9.0)\n",
      "Requirement already satisfied: nest-asyncio in /home/user/.local/lib/python3.10/site-packages (from ipykernel->jupyter) (1.5.6)\n",
      "Requirement already satisfied: psutil in /home/user/.local/lib/python3.10/site-packages (from ipykernel->jupyter) (5.9.5)\n",
      "Requirement already satisfied: jupyter-core!=5.0.*,>=4.12 in /home/user/.local/lib/python3.10/site-packages (from ipykernel->jupyter) (5.3.1)\n",
      "Requirement already satisfied: tornado>=6.1 in /home/user/.local/lib/python3.10/site-packages (from ipykernel->jupyter) (6.3.2)\n",
      "Requirement already satisfied: ipython>=7.23.1 in /home/user/.local/lib/python3.10/site-packages (from ipykernel->jupyter) (8.14.0)\n",
      "Requirement already satisfied: jupyterlab-widgets~=3.0.7 in /home/user/.local/lib/python3.10/site-packages (from ipywidgets->jupyter) (3.0.7)\n",
      "Requirement already satisfied: widgetsnbextension~=4.0.7 in /home/user/.local/lib/python3.10/site-packages (from ipywidgets->jupyter) (4.0.7)\n",
      "Requirement already satisfied: pygments in /usr/lib/python3/dist-packages (from jupyter-console->jupyter) (2.11.2)\n",
      "Requirement already satisfied: prompt-toolkit>=3.0.30 in /home/user/.local/lib/python3.10/site-packages (from jupyter-console->jupyter) (3.0.38)\n",
      "Requirement already satisfied: bleach!=5.0.0 in /home/user/.local/lib/python3.10/site-packages (from nbconvert->jupyter) (6.0.0)\n",
      "Requirement already satisfied: nbformat>=5.7 in /home/user/.local/lib/python3.10/site-packages (from nbconvert->jupyter) (5.9.0)\n",
      "Requirement already satisfied: pandocfilters>=1.4.1 in /home/user/.local/lib/python3.10/site-packages (from nbconvert->jupyter) (1.5.0)\n",
      "Requirement already satisfied: mistune<4,>=2.0.3 in /home/user/.local/lib/python3.10/site-packages (from nbconvert->jupyter) (3.0.1)\n",
      "Requirement already satisfied: jupyterlab-pygments in /home/user/.local/lib/python3.10/site-packages (from nbconvert->jupyter) (0.2.2)\n",
      "Requirement already satisfied: nbclient>=0.5.0 in /home/user/.local/lib/python3.10/site-packages (from nbconvert->jupyter) (0.8.0)\n",
      "Requirement already satisfied: defusedxml in /home/user/.local/lib/python3.10/site-packages (from nbconvert->jupyter) (0.7.1)\n",
      "Requirement already satisfied: tinycss2 in /home/user/.local/lib/python3.10/site-packages (from nbconvert->jupyter) (1.2.1)\n",
      "Requirement already satisfied: beautifulsoup4 in /usr/lib/python3/dist-packages (from nbconvert->jupyter) (4.10.0)\n",
      "Requirement already satisfied: markupsafe>=2.0 in /home/user/.local/lib/python3.10/site-packages (from nbconvert->jupyter) (2.1.3)\n",
      "Requirement already satisfied: click in /usr/lib/python3/dist-packages (from nltk->sentence_transformers) (8.0.3)\n",
      "Requirement already satisfied: joblib in /home/user/.local/lib/python3.10/site-packages (from nltk->sentence_transformers) (1.3.1)\n",
      "Requirement already satisfied: terminado>=0.8.3 in /home/user/.local/lib/python3.10/site-packages (from notebook->jupyter) (0.17.1)\n",
      "Requirement already satisfied: Send2Trash>=1.8.0 in /home/user/.local/lib/python3.10/site-packages (from notebook->jupyter) (1.8.2)\n",
      "Requirement already satisfied: ipython-genutils in /home/user/.local/lib/python3.10/site-packages (from notebook->jupyter) (0.2.0)\n",
      "Requirement already satisfied: argon2-cffi in /home/user/.local/lib/python3.10/site-packages (from notebook->jupyter) (21.3.0)\n",
      "Requirement already satisfied: prometheus-client in /home/user/.local/lib/python3.10/site-packages (from notebook->jupyter) (0.17.0)\n",
      "Requirement already satisfied: nbclassic>=0.4.7 in /home/user/.local/lib/python3.10/site-packages (from notebook->jupyter) (1.0.0)\n",
      "Requirement already satisfied: qtpy>=2.0.1 in /home/user/.local/lib/python3.10/site-packages (from qtconsole->jupyter) (2.3.1)\n",
      "Requirement already satisfied: threadpoolctl>=2.0.0 in /home/user/.local/lib/python3.10/site-packages (from scikit-learn->sentence_transformers) (3.1.0)\n",
      "Requirement already satisfied: pillow!=8.3.*,>=5.3.0 in /usr/lib/python3/dist-packages (from torchvision->sentence_transformers) (9.0.1)\n",
      "Requirement already satisfied: webencodings in /usr/lib/python3/dist-packages (from bleach!=5.0.0->nbconvert->jupyter) (0.5.1)\n",
      "Requirement already satisfied: hpack<5,>=4.0 in /home/user/.local/lib/python3.10/site-packages (from h2<5,>=3->httpx[http2]>=0.14.0->qdrant_client~=1.3.0) (4.0.0)\n",
      "Requirement already satisfied: hyperframe<7,>=6.0 in /home/user/.local/lib/python3.10/site-packages (from h2<5,>=3->httpx[http2]>=0.14.0->qdrant_client~=1.3.0) (6.0.1)\n",
      "Requirement already satisfied: anyio<5.0,>=3.0 in /home/user/.local/lib/python3.10/site-packages (from httpcore<0.18.0,>=0.15.0->httpx[http2]>=0.14.0->qdrant_client~=1.3.0) (3.7.0)\n",
      "Requirement already satisfied: h11<0.15,>=0.13 in /home/user/.local/lib/python3.10/site-packages (from httpcore<0.18.0,>=0.15.0->httpx[http2]>=0.14.0->qdrant_client~=1.3.0) (0.14.0)\n",
      "Requirement already satisfied: stack-data in /home/user/.local/lib/python3.10/site-packages (from ipython>=7.23.1->ipykernel->jupyter) (0.6.2)\n",
      "Requirement already satisfied: pickleshare in /home/user/.local/lib/python3.10/site-packages (from ipython>=7.23.1->ipykernel->jupyter) (0.7.5)\n",
      "Requirement already satisfied: backcall in /home/user/.local/lib/python3.10/site-packages (from ipython>=7.23.1->ipykernel->jupyter) (0.2.0)\n",
      "Requirement already satisfied: jedi>=0.16 in /home/user/.local/lib/python3.10/site-packages (from ipython>=7.23.1->ipykernel->jupyter) (0.18.2)\n",
      "Requirement already satisfied: pexpect>4.3 in /usr/lib/python3/dist-packages (from ipython>=7.23.1->ipykernel->jupyter) (4.8.0)\n",
      "Requirement already satisfied: decorator in /home/user/.local/lib/python3.10/site-packages (from ipython>=7.23.1->ipykernel->jupyter) (5.1.1)\n",
      "Requirement already satisfied: platformdirs>=2.5 in /home/user/.local/lib/python3.10/site-packages (from jupyter-core!=5.0.*,>=4.12->ipykernel->jupyter) (2.6.2)\n",
      "Requirement already satisfied: notebook-shim>=0.2.3 in /home/user/.local/lib/python3.10/site-packages (from nbclassic>=0.4.7->notebook->jupyter) (0.2.3)\n",
      "Requirement already satisfied: jupyter-server>=1.8 in /home/user/.local/lib/python3.10/site-packages (from nbclassic>=0.4.7->notebook->jupyter) (2.7.0)\n",
      "Requirement already satisfied: jsonschema>=2.6 in /home/user/.local/lib/python3.10/site-packages (from nbformat>=5.7->nbconvert->jupyter) (4.17.3)\n",
      "Requirement already satisfied: fastjsonschema in /home/user/.local/lib/python3.10/site-packages (from nbformat>=5.7->nbconvert->jupyter) (2.17.1)\n",
      "Requirement already satisfied: wcwidth in /home/user/.local/lib/python3.10/site-packages (from prompt-toolkit>=3.0.30->jupyter-console->jupyter) (0.2.6)\n",
      "Requirement already satisfied: ptyprocess in /usr/lib/python3/dist-packages (from terminado>=0.8.3->notebook->jupyter) (0.7.0)\n",
      "Requirement already satisfied: argon2-cffi-bindings in /home/user/.local/lib/python3.10/site-packages (from argon2-cffi->notebook->jupyter) (21.2.0)\n",
      "Requirement already satisfied: mpmath>=0.19 in /home/user/.local/lib/python3.10/site-packages (from sympy->torch>=1.6.0->sentence_transformers) (1.3.0)\n",
      "Requirement already satisfied: exceptiongroup in /home/user/.local/lib/python3.10/site-packages (from anyio<5.0,>=3.0->httpcore<0.18.0,>=0.15.0->httpx[http2]>=0.14.0->qdrant_client~=1.3.0) (1.1.1)\n",
      "Requirement already satisfied: parso<0.9.0,>=0.8.0 in /home/user/.local/lib/python3.10/site-packages (from jedi>=0.16->ipython>=7.23.1->ipykernel->jupyter) (0.8.3)\n",
      "Requirement already satisfied: attrs>=17.4.0 in /usr/lib/python3/dist-packages (from jsonschema>=2.6->nbformat>=5.7->nbconvert->jupyter) (21.2.0)\n",
      "Requirement already satisfied: pyrsistent!=0.17.0,!=0.17.1,!=0.17.2,>=0.14.0 in /usr/lib/python3/dist-packages (from jsonschema>=2.6->nbformat>=5.7->nbconvert->jupyter) (0.18.1)\n",
      "Requirement already satisfied: overrides in /home/user/.local/lib/python3.10/site-packages (from jupyter-server>=1.8->nbclassic>=0.4.7->notebook->jupyter) (7.3.1)\n",
      "Requirement already satisfied: websocket-client in /usr/lib/python3/dist-packages (from jupyter-server>=1.8->nbclassic>=0.4.7->notebook->jupyter) (1.2.3)\n",
      "Requirement already satisfied: jupyter-server-terminals in /home/user/.local/lib/python3.10/site-packages (from jupyter-server>=1.8->nbclassic>=0.4.7->notebook->jupyter) (0.4.4)\n",
      "Requirement already satisfied: jupyter-events>=0.6.0 in /home/user/.local/lib/python3.10/site-packages (from jupyter-server>=1.8->nbclassic>=0.4.7->notebook->jupyter) (0.6.3)\n",
      "Requirement already satisfied: cffi>=1.0.1 in /home/user/.local/lib/python3.10/site-packages (from argon2-cffi-bindings->argon2-cffi->notebook->jupyter) (1.15.1)\n",
      "Requirement already satisfied: asttokens>=2.1.0 in /home/user/.local/lib/python3.10/site-packages (from stack-data->ipython>=7.23.1->ipykernel->jupyter) (2.2.1)\n",
      "Requirement already satisfied: executing>=1.2.0 in /home/user/.local/lib/python3.10/site-packages (from stack-data->ipython>=7.23.1->ipykernel->jupyter) (1.2.0)\n",
      "Requirement already satisfied: pure-eval in /home/user/.local/lib/python3.10/site-packages (from stack-data->ipython>=7.23.1->ipykernel->jupyter) (0.2.2)\n",
      "Requirement already satisfied: pycparser in /home/user/.local/lib/python3.10/site-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi->notebook->jupyter) (2.21)\n",
      "Requirement already satisfied: rfc3339-validator in /home/user/.local/lib/python3.10/site-packages (from jupyter-events>=0.6.0->jupyter-server>=1.8->nbclassic>=0.4.7->notebook->jupyter) (0.1.4)\n",
      "Requirement already satisfied: rfc3986-validator>=0.1.1 in /home/user/.local/lib/python3.10/site-packages (from jupyter-events>=0.6.0->jupyter-server>=1.8->nbclassic>=0.4.7->notebook->jupyter) (0.1.1)\n",
      "Requirement already satisfied: python-json-logger>=2.0.4 in /home/user/.local/lib/python3.10/site-packages (from jupyter-events>=0.6.0->jupyter-server>=1.8->nbclassic>=0.4.7->notebook->jupyter) (2.0.7)\n",
      "Requirement already satisfied: webcolors>=1.11 in /home/user/.local/lib/python3.10/site-packages (from jsonschema>=2.6->nbformat>=5.7->nbconvert->jupyter) (1.13)\n",
      "Requirement already satisfied: fqdn in /home/user/.local/lib/python3.10/site-packages (from jsonschema>=2.6->nbformat>=5.7->nbconvert->jupyter) (1.5.1)\n",
      "Requirement already satisfied: isoduration in /home/user/.local/lib/python3.10/site-packages (from jsonschema>=2.6->nbformat>=5.7->nbconvert->jupyter) (20.11.0)\n",
      "Requirement already satisfied: uri-template in /home/user/.local/lib/python3.10/site-packages (from jsonschema>=2.6->nbformat>=5.7->nbconvert->jupyter) (1.3.0)\n",
      "Requirement already satisfied: jsonpointer>1.13 in /home/user/.local/lib/python3.10/site-packages (from jsonschema>=2.6->nbformat>=5.7->nbconvert->jupyter) (2.4)\n",
      "Requirement already satisfied: arrow>=0.15.0 in /home/user/.local/lib/python3.10/site-packages (from isoduration->jsonschema>=2.6->nbformat>=5.7->nbconvert->jupyter) (1.2.3)\n",
      "\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip available: \u001b[0m\u001b[31;49m22.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m23.2\u001b[0m\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython3 -m pip install --upgrade pip\u001b[0m\n"
     ]
    }
   ],
   "source": [
    "!pip install jupyter pandas sentence_transformers \"qdrant_client~=1.3.0\" pyarrow"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The dataset is provided as a CSV file and contains multiple attributes of the products, including URLs of the product images. That gives us a real case to work on. Let's check the dataset structure and prepare it for further processing.\n",
    "\n",
    "**For the testing purposes, we can use only a small subset of the dataset. It's enough to show the concept, but you can easily scale it to the whole dataset. The variable below is a fraction of the dataset that will be used for the rest of the notebook. Feel free to change it to `1.0` if you want to use the whole dataset.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:11:54.881549Z",
     "start_time": "2023-07-20T09:11:54.875438Z"
    }
   },
   "outputs": [],
   "source": [
    "DATASET_FRACTION = 0.1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, we can load the dataset and see what it contains."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:11:55.716143Z",
     "start_time": "2023-07-20T09:11:54.885807Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>8275</th>\n",
       "      <th>8165</th>\n",
       "      <th>6207</th>\n",
       "      <th>5179</th>\n",
       "      <th>8976</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Uniq Id</th>\n",
       "      <td>1e9d1ef6a6ad5b3a1f5eebbd53484138</td>\n",
       "      <td>8fbe83e06a8dc8d980eef095230f0a35</td>\n",
       "      <td>f0500baf3d8b5aa1bd8b8c39b403005f</td>\n",
       "      <td>611dcf8d0ab97f05538325b3325e7d6f</td>\n",
       "      <td>23e07aa25d12fa2e3ec9f4fab3ae7c27</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Name</th>\n",
       "      <td>MightySkins Skin Compatible with Razor Turbo J...</td>\n",
       "      <td>Franklin Sports Aquaticz Target Twisters Water...</td>\n",
       "      <td>Icon Heroes Once Upon A Time: Emma Swan Action...</td>\n",
       "      <td>Creative Cedar Designs Playset Telescope Acces...</td>\n",
       "      <td>LEGO DUPLO Town Tropical Island 10906 Building...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Brand Name</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Asin</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Category</th>\n",
       "      <td>Sports &amp; Outdoors | Outdoor Recreation | Skate...</td>\n",
       "      <td>Toys &amp; Games | Baby &amp; Toddler Toys | Bath Toys</td>\n",
       "      <td>Toys &amp; Games | Collectible Toys | Statues, Bob...</td>\n",
       "      <td>Toys &amp; Games | Learning &amp; Education | Optics |...</td>\n",
       "      <td>Toys &amp; Games | Building Toys | Building Sets</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Upc Ean Code</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>List Price</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Selling Price</th>\n",
       "      <td>$19.99</td>\n",
       "      <td>$39.18</td>\n",
       "      <td>$11.99</td>\n",
       "      <td>$15.99</td>\n",
       "      <td>$54.28</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Quantity</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Model Number</th>\n",
       "      <td>RATUJE-Pastel Chevron</td>\n",
       "      <td>52696</td>\n",
       "      <td>JUL162847</td>\n",
       "      <td>NaN</td>\n",
       "      <td>6250750</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>About Product</th>\n",
       "      <td>RIDE IN STYLE: Show off your own unique style ...</td>\n",
       "      <td>Make sure this fits by entering your model num...</td>\n",
       "      <td>Make sure this fits by entering your model num...</td>\n",
       "      <td>Make sure this fits by entering your model num...</td>\n",
       "      <td>Make sure this fits by entering your model num...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Specification</th>\n",
       "      <td>ProductDimensions:10x0.1x14inches|ItemWeight:0...</td>\n",
       "      <td>ProductDimensions:15x15x20.5inches|ItemWeight:...</td>\n",
       "      <td>ProductDimensions:2x1x6inches|ItemWeight:1.44o...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>ProductDimensions:18.9x14.9x3.7inches|ItemWeig...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Technical Details</th>\n",
       "      <td>Go to your orders and start the return Select ...</td>\n",
       "      <td>show up to 2 reviews by default The Aquaticz T...</td>\n",
       "      <td>Go to your orders and start the return Select ...</td>\n",
       "      <td>Go to your orders and start the return Select ...</td>\n",
       "      <td>Go to your orders and start the return Select ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Shipping Weight</th>\n",
       "      <td>0.96 ounces</td>\n",
       "      <td>5.5 pounds</td>\n",
       "      <td>1.44 ounces</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2.91 pounds</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Dimensions</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Image</th>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Variants</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>https://www.amazon.com/CREATIVE-CEDAR-DESIGNS-...</td>\n",
       "      <td>https://www.amazon.com/LEGO-Tropical-Island-Bu...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Sku</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Url</th>\n",
       "      <td>https://www.amazon.com/MightySkins-Turbo-Jetts...</td>\n",
       "      <td>https://www.amazon.com/Franklin-Sports-Aquatic...</td>\n",
       "      <td>https://www.amazon.com/Icon-Heroes-Once-Upon-T...</td>\n",
       "      <td>https://www.amazon.com/CREATIVE-CEDAR-DESIGNS-...</td>\n",
       "      <td>https://www.amazon.com/LEGO-Tropical-Island-Bu...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Stock</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Details</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Dimensions</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Color</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Ingredients</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Direction To Use</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Is Amazon Seller</th>\n",
       "      <td>Y</td>\n",
       "      <td>Y</td>\n",
       "      <td>Y</td>\n",
       "      <td>Y</td>\n",
       "      <td>Y</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Size Quantity Variant</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Description</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                                    8275  \\\n",
       "Uniq Id                                 1e9d1ef6a6ad5b3a1f5eebbd53484138   \n",
       "Product Name           MightySkins Skin Compatible with Razor Turbo J...   \n",
       "Brand Name                                                           NaN   \n",
       "Asin                                                                 NaN   \n",
       "Category               Sports & Outdoors | Outdoor Recreation | Skate...   \n",
       "Upc Ean Code                                                         NaN   \n",
       "List Price                                                           NaN   \n",
       "Selling Price                                                     $19.99   \n",
       "Quantity                                                             NaN   \n",
       "Model Number                                       RATUJE-Pastel Chevron   \n",
       "About Product          RIDE IN STYLE: Show off your own unique style ...   \n",
       "Product Specification  ProductDimensions:10x0.1x14inches|ItemWeight:0...   \n",
       "Technical Details      Go to your orders and start the return Select ...   \n",
       "Shipping Weight                                              0.96 ounces   \n",
       "Product Dimensions                                                   NaN   \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...   \n",
       "Variants                                                             NaN   \n",
       "Sku                                                                  NaN   \n",
       "Product Url            https://www.amazon.com/MightySkins-Turbo-Jetts...   \n",
       "Stock                                                                NaN   \n",
       "Product Details                                                      NaN   \n",
       "Dimensions                                                           NaN   \n",
       "Color                                                                NaN   \n",
       "Ingredients                                                          NaN   \n",
       "Direction To Use                                                     NaN   \n",
       "Is Amazon Seller                                                       Y   \n",
       "Size Quantity Variant                                                NaN   \n",
       "Product Description                                                  NaN   \n",
       "\n",
       "                                                                    8165  \\\n",
       "Uniq Id                                 8fbe83e06a8dc8d980eef095230f0a35   \n",
       "Product Name           Franklin Sports Aquaticz Target Twisters Water...   \n",
       "Brand Name                                                           NaN   \n",
       "Asin                                                                 NaN   \n",
       "Category                  Toys & Games | Baby & Toddler Toys | Bath Toys   \n",
       "Upc Ean Code                                                         NaN   \n",
       "List Price                                                           NaN   \n",
       "Selling Price                                                     $39.18   \n",
       "Quantity                                                             NaN   \n",
       "Model Number                                                       52696   \n",
       "About Product          Make sure this fits by entering your model num...   \n",
       "Product Specification  ProductDimensions:15x15x20.5inches|ItemWeight:...   \n",
       "Technical Details      show up to 2 reviews by default The Aquaticz T...   \n",
       "Shipping Weight                                               5.5 pounds   \n",
       "Product Dimensions                                                   NaN   \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...   \n",
       "Variants                                                             NaN   \n",
       "Sku                                                                  NaN   \n",
       "Product Url            https://www.amazon.com/Franklin-Sports-Aquatic...   \n",
       "Stock                                                                NaN   \n",
       "Product Details                                                      NaN   \n",
       "Dimensions                                                           NaN   \n",
       "Color                                                                NaN   \n",
       "Ingredients                                                          NaN   \n",
       "Direction To Use                                                     NaN   \n",
       "Is Amazon Seller                                                       Y   \n",
       "Size Quantity Variant                                                NaN   \n",
       "Product Description                                                  NaN   \n",
       "\n",
       "                                                                    6207  \\\n",
       "Uniq Id                                 f0500baf3d8b5aa1bd8b8c39b403005f   \n",
       "Product Name           Icon Heroes Once Upon A Time: Emma Swan Action...   \n",
       "Brand Name                                                           NaN   \n",
       "Asin                                                                 NaN   \n",
       "Category               Toys & Games | Collectible Toys | Statues, Bob...   \n",
       "Upc Ean Code                                                         NaN   \n",
       "List Price                                                           NaN   \n",
       "Selling Price                                                     $11.99   \n",
       "Quantity                                                             NaN   \n",
       "Model Number                                                   JUL162847   \n",
       "About Product          Make sure this fits by entering your model num...   \n",
       "Product Specification  ProductDimensions:2x1x6inches|ItemWeight:1.44o...   \n",
       "Technical Details      Go to your orders and start the return Select ...   \n",
       "Shipping Weight                                              1.44 ounces   \n",
       "Product Dimensions                                                   NaN   \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...   \n",
       "Variants                                                             NaN   \n",
       "Sku                                                                  NaN   \n",
       "Product Url            https://www.amazon.com/Icon-Heroes-Once-Upon-T...   \n",
       "Stock                                                                NaN   \n",
       "Product Details                                                      NaN   \n",
       "Dimensions                                                           NaN   \n",
       "Color                                                                NaN   \n",
       "Ingredients                                                          NaN   \n",
       "Direction To Use                                                     NaN   \n",
       "Is Amazon Seller                                                       Y   \n",
       "Size Quantity Variant                                                NaN   \n",
       "Product Description                                                  NaN   \n",
       "\n",
       "                                                                    5179  \\\n",
       "Uniq Id                                 611dcf8d0ab97f05538325b3325e7d6f   \n",
       "Product Name           Creative Cedar Designs Playset Telescope Acces...   \n",
       "Brand Name                                                           NaN   \n",
       "Asin                                                                 NaN   \n",
       "Category               Toys & Games | Learning & Education | Optics |...   \n",
       "Upc Ean Code                                                         NaN   \n",
       "List Price                                                           NaN   \n",
       "Selling Price                                                     $15.99   \n",
       "Quantity                                                             NaN   \n",
       "Model Number                                                         NaN   \n",
       "About Product          Make sure this fits by entering your model num...   \n",
       "Product Specification                                                NaN   \n",
       "Technical Details      Go to your orders and start the return Select ...   \n",
       "Shipping Weight                                                      NaN   \n",
       "Product Dimensions                                                   NaN   \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...   \n",
       "Variants               https://www.amazon.com/CREATIVE-CEDAR-DESIGNS-...   \n",
       "Sku                                                                  NaN   \n",
       "Product Url            https://www.amazon.com/CREATIVE-CEDAR-DESIGNS-...   \n",
       "Stock                                                                NaN   \n",
       "Product Details                                                      NaN   \n",
       "Dimensions                                                           NaN   \n",
       "Color                                                                NaN   \n",
       "Ingredients                                                          NaN   \n",
       "Direction To Use                                                     NaN   \n",
       "Is Amazon Seller                                                       Y   \n",
       "Size Quantity Variant                                                NaN   \n",
       "Product Description                                                  NaN   \n",
       "\n",
       "                                                                    8976  \n",
       "Uniq Id                                 23e07aa25d12fa2e3ec9f4fab3ae7c27  \n",
       "Product Name           LEGO DUPLO Town Tropical Island 10906 Building...  \n",
       "Brand Name                                                           NaN  \n",
       "Asin                                                                 NaN  \n",
       "Category                    Toys & Games | Building Toys | Building Sets  \n",
       "Upc Ean Code                                                         NaN  \n",
       "List Price                                                           NaN  \n",
       "Selling Price                                                     $54.28  \n",
       "Quantity                                                             NaN  \n",
       "Model Number                                                     6250750  \n",
       "About Product          Make sure this fits by entering your model num...  \n",
       "Product Specification  ProductDimensions:18.9x14.9x3.7inches|ItemWeig...  \n",
       "Technical Details      Go to your orders and start the return Select ...  \n",
       "Shipping Weight                                              2.91 pounds  \n",
       "Product Dimensions                                                   NaN  \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...  \n",
       "Variants               https://www.amazon.com/LEGO-Tropical-Island-Bu...  \n",
       "Sku                                                                  NaN  \n",
       "Product Url            https://www.amazon.com/LEGO-Tropical-Island-Bu...  \n",
       "Stock                                                                NaN  \n",
       "Product Details                                                      NaN  \n",
       "Dimensions                                                           NaN  \n",
       "Color                                                                NaN  \n",
       "Ingredients                                                          NaN  \n",
       "Direction To Use                                                     NaN  \n",
       "Is Amazon Seller                                                       Y  \n",
       "Size Quantity Variant                                                NaN  \n",
       "Product Description                                                  NaN  "
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import zipfile\n",
    "\n",
    "with zipfile.ZipFile(\"./data/amazon-product-dataset-2020.zip\", \"r\") as z:\n",
    "    with z.open(\"home/sdf/marketing_sample_for_amazon_com-ecommerce__20200101_20200131__10k_data.csv\") as f:\n",
    "        dataset_df = pd.read_csv(f).sample(frac=DATASET_FRACTION)\n",
    "        \n",
    "dataset_df.sample(n=5).T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:11:55.721463Z",
     "start_time": "2023-07-20T09:11:55.717905Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1000, 28)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataset_df.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:11:55.734587Z",
     "start_time": "2023-07-20T09:11:55.723111Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'https://images-na.ssl-images-amazon.com/images/I/21ibn-69NWL.jpg|https://images-na.ssl-images-amazon.com/images/I/51CXFytZv4L.jpg|https://images-na.ssl-images-amazon.com/images/I/516QstsWMAL.jpg|https://images-na.ssl-images-amazon.com/images/I/51k3Jgl9OjL.jpg|https://images-na.ssl-images-amazon.com/images/G/01/x-locale/common/transparent-pixel.jpg'"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataset_df.iloc[0][\"Image\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It turns out a single product may have several images. They are stored in a pipe-separated string."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:11:55.740435Z",
     "start_time": "2023-07-20T09:11:55.736888Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['https://images-na.ssl-images-amazon.com/images/I/21ibn-69NWL.jpg',\n",
       " 'https://images-na.ssl-images-amazon.com/images/I/51CXFytZv4L.jpg',\n",
       " 'https://images-na.ssl-images-amazon.com/images/I/516QstsWMAL.jpg',\n",
       " 'https://images-na.ssl-images-amazon.com/images/I/51k3Jgl9OjL.jpg',\n",
       " 'https://images-na.ssl-images-amazon.com/images/G/01/x-locale/common/transparent-pixel.jpg']"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataset_df.iloc[0][\"Image\"].split(\"|\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The last entry is common for multiple products, so we can simply remove it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:11:55.746874Z",
     "start_time": "2023-07-20T09:11:55.742074Z"
    }
   },
   "outputs": [],
   "source": [
    "dataset_df[\"Image\"] = dataset_df[\"Image\"].map(lambda x: x.split(\"|\")[:-1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:11:55.755008Z",
     "start_time": "2023-07-20T09:11:55.749269Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['https://images-na.ssl-images-amazon.com/images/I/21ibn-69NWL.jpg',\n",
       " 'https://images-na.ssl-images-amazon.com/images/I/51CXFytZv4L.jpg',\n",
       " 'https://images-na.ssl-images-amazon.com/images/I/516QstsWMAL.jpg',\n",
       " 'https://images-na.ssl-images-amazon.com/images/I/51k3Jgl9OjL.jpg']"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataset_df.iloc[0][\"Image\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:11:55.776871Z",
     "start_time": "2023-07-20T09:11:55.756290Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>4564</th>\n",
       "      <th>3441</th>\n",
       "      <th>28</th>\n",
       "      <th>6643</th>\n",
       "      <th>1940</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Uniq Id</th>\n",
       "      <td>e1c2b6aa8735a8d858c20678992aabf4</td>\n",
       "      <td>ea63d38452a33cb5fc94d8e139a9d0bf</td>\n",
       "      <td>fdd8daf07ddd4a23832f3da7d209252f</td>\n",
       "      <td>cff2276b08e7a89c08f51ddeeb41d2a3</td>\n",
       "      <td>7696da17a6ac24c862f0df8017ed8fbf</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Name</th>\n",
       "      <td>Step2 Modern Metro Kitchen | Modern Play Kitch...</td>\n",
       "      <td>Flagship Carpets FE102-70A Multiply and Divide...</td>\n",
       "      <td>Oopsy Daisy Birchwood Owl Growth Chart, Pink, ...</td>\n",
       "      <td>Folkmanis Collared Lizard Hand Puppet Plush</td>\n",
       "      <td>Kids First Engineering Design Physics Lab Scie...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Brand Name</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Asin</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Category</th>\n",
       "      <td>Toys &amp; Games | Dress Up &amp; Pretend Play | Prete...</td>\n",
       "      <td>Home &amp; Kitchen | Home Décor | Kids' Room Décor...</td>\n",
       "      <td>Baby Products | Nursery | Décor | Wall Décor |...</td>\n",
       "      <td>Toys &amp; Games | Puppets &amp; Puppet Theaters | Han...</td>\n",
       "      <td>Toys &amp; Games | Learning &amp; Education | Science ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Upc Ean Code</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>List Price</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Selling Price</th>\n",
       "      <td>$142.99</td>\n",
       "      <td>$59.99</td>\n",
       "      <td>$18.70</td>\n",
       "      <td>$31.41</td>\n",
       "      <td>$27.99</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Quantity</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Model Number</th>\n",
       "      <td>879799</td>\n",
       "      <td>FE102-70A</td>\n",
       "      <td>NB19671</td>\n",
       "      <td>3063</td>\n",
       "      <td>628318</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>About Product</th>\n",
       "      <td>Make sure this fits by entering your model num...</td>\n",
       "      <td>Make sure this fits by entering your model num...</td>\n",
       "      <td>Art by Jen Christopher | Color-coordinated dec...</td>\n",
       "      <td>Make sure this fits by entering your model num...</td>\n",
       "      <td>Make sure this fits by entering your model num...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Specification</th>\n",
       "      <td>ProductDimensions:46.5x14x44.8inches|ItemWeigh...</td>\n",
       "      <td>Product Dimensions:         144 x 144 x 0.5 in...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>ProductDimensions:17x7x10inches|ItemWeight:1.6...</td>\n",
       "      <td>ProductDimensions:16.8x11.5x3.2inches|ItemWeig...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Technical Details</th>\n",
       "      <td>Juniors chefs will be busy baking away with th...</td>\n",
       "      <td>Size:12' X 12' Multiplication is no problem wh...</td>\n",
       "      <td>Go to Your Orders to start the return Print th...</td>\n",
       "      <td>Whether sunning itself on a rock or scurrying ...</td>\n",
       "      <td>Go to your orders and start the return Select ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Shipping Weight</th>\n",
       "      <td>38.6 pounds</td>\n",
       "      <td>70 pounds</td>\n",
       "      <td>13.6 ounces</td>\n",
       "      <td>1.6 ounces</td>\n",
       "      <td>2.75 pounds</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Dimensions</th>\n",
       "      <td>NaN</td>\n",
       "      <td>144 x 144 x 0.5 inches  70 pounds</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Image</th>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Variants</th>\n",
       "      <td>NaN</td>\n",
       "      <td>https://www.amazon.com/Flagship-Carpets-FE102-...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Sku</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Url</th>\n",
       "      <td>https://www.amazon.com/Step2-Modern-Metro-Kitc...</td>\n",
       "      <td>https://www.amazon.com/Flagship-Carpets-FE102-...</td>\n",
       "      <td>https://www.amazon.com/Oopsy-Daisy-Birchwood-G...</td>\n",
       "      <td>https://www.amazon.com/Folkmanis-Collared-Liza...</td>\n",
       "      <td>https://www.amazon.com/Kids-First-Engineering-...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Stock</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Details</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Dimensions</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Color</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Ingredients</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Direction To Use</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Is Amazon Seller</th>\n",
       "      <td>Y</td>\n",
       "      <td>N</td>\n",
       "      <td>Y</td>\n",
       "      <td>Y</td>\n",
       "      <td>Y</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Size Quantity Variant</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Description</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                                    4564  \\\n",
       "Uniq Id                                 e1c2b6aa8735a8d858c20678992aabf4   \n",
       "Product Name           Step2 Modern Metro Kitchen | Modern Play Kitch...   \n",
       "Brand Name                                                           NaN   \n",
       "Asin                                                                 NaN   \n",
       "Category               Toys & Games | Dress Up & Pretend Play | Prete...   \n",
       "Upc Ean Code                                                         NaN   \n",
       "List Price                                                           NaN   \n",
       "Selling Price                                                    $142.99   \n",
       "Quantity                                                             NaN   \n",
       "Model Number                                                      879799   \n",
       "About Product          Make sure this fits by entering your model num...   \n",
       "Product Specification  ProductDimensions:46.5x14x44.8inches|ItemWeigh...   \n",
       "Technical Details      Juniors chefs will be busy baking away with th...   \n",
       "Shipping Weight                                              38.6 pounds   \n",
       "Product Dimensions                                                   NaN   \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...   \n",
       "Variants                                                             NaN   \n",
       "Sku                                                                  NaN   \n",
       "Product Url            https://www.amazon.com/Step2-Modern-Metro-Kitc...   \n",
       "Stock                                                                NaN   \n",
       "Product Details                                                      NaN   \n",
       "Dimensions                                                           NaN   \n",
       "Color                                                                NaN   \n",
       "Ingredients                                                          NaN   \n",
       "Direction To Use                                                     NaN   \n",
       "Is Amazon Seller                                                       Y   \n",
       "Size Quantity Variant                                                NaN   \n",
       "Product Description                                                  NaN   \n",
       "\n",
       "                                                                    3441  \\\n",
       "Uniq Id                                 ea63d38452a33cb5fc94d8e139a9d0bf   \n",
       "Product Name           Flagship Carpets FE102-70A Multiply and Divide...   \n",
       "Brand Name                                                           NaN   \n",
       "Asin                                                                 NaN   \n",
       "Category               Home & Kitchen | Home Décor | Kids' Room Décor...   \n",
       "Upc Ean Code                                                         NaN   \n",
       "List Price                                                           NaN   \n",
       "Selling Price                                                     $59.99   \n",
       "Quantity                                                             NaN   \n",
       "Model Number                                                   FE102-70A   \n",
       "About Product          Make sure this fits by entering your model num...   \n",
       "Product Specification  Product Dimensions:         144 x 144 x 0.5 in...   \n",
       "Technical Details      Size:12' X 12' Multiplication is no problem wh...   \n",
       "Shipping Weight                                                70 pounds   \n",
       "Product Dimensions                     144 x 144 x 0.5 inches  70 pounds   \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...   \n",
       "Variants               https://www.amazon.com/Flagship-Carpets-FE102-...   \n",
       "Sku                                                                  NaN   \n",
       "Product Url            https://www.amazon.com/Flagship-Carpets-FE102-...   \n",
       "Stock                                                                NaN   \n",
       "Product Details                                                      NaN   \n",
       "Dimensions                                                           NaN   \n",
       "Color                                                                NaN   \n",
       "Ingredients                                                          NaN   \n",
       "Direction To Use                                                     NaN   \n",
       "Is Amazon Seller                                                       N   \n",
       "Size Quantity Variant                                                NaN   \n",
       "Product Description                                                  NaN   \n",
       "\n",
       "                                                                    28    \\\n",
       "Uniq Id                                 fdd8daf07ddd4a23832f3da7d209252f   \n",
       "Product Name           Oopsy Daisy Birchwood Owl Growth Chart, Pink, ...   \n",
       "Brand Name                                                           NaN   \n",
       "Asin                                                                 NaN   \n",
       "Category               Baby Products | Nursery | Décor | Wall Décor |...   \n",
       "Upc Ean Code                                                         NaN   \n",
       "List Price                                                           NaN   \n",
       "Selling Price                                                     $18.70   \n",
       "Quantity                                                             NaN   \n",
       "Model Number                                                     NB19671   \n",
       "About Product          Art by Jen Christopher | Color-coordinated dec...   \n",
       "Product Specification                                                NaN   \n",
       "Technical Details      Go to Your Orders to start the return Print th...   \n",
       "Shipping Weight                                              13.6 ounces   \n",
       "Product Dimensions                                                   NaN   \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...   \n",
       "Variants                                                             NaN   \n",
       "Sku                                                                  NaN   \n",
       "Product Url            https://www.amazon.com/Oopsy-Daisy-Birchwood-G...   \n",
       "Stock                                                                NaN   \n",
       "Product Details                                                      NaN   \n",
       "Dimensions                                                           NaN   \n",
       "Color                                                                NaN   \n",
       "Ingredients                                                          NaN   \n",
       "Direction To Use                                                     NaN   \n",
       "Is Amazon Seller                                                       Y   \n",
       "Size Quantity Variant                                                NaN   \n",
       "Product Description                                                  NaN   \n",
       "\n",
       "                                                                    6643  \\\n",
       "Uniq Id                                 cff2276b08e7a89c08f51ddeeb41d2a3   \n",
       "Product Name                 Folkmanis Collared Lizard Hand Puppet Plush   \n",
       "Brand Name                                                           NaN   \n",
       "Asin                                                                 NaN   \n",
       "Category               Toys & Games | Puppets & Puppet Theaters | Han...   \n",
       "Upc Ean Code                                                         NaN   \n",
       "List Price                                                           NaN   \n",
       "Selling Price                                                     $31.41   \n",
       "Quantity                                                             NaN   \n",
       "Model Number                                                        3063   \n",
       "About Product          Make sure this fits by entering your model num...   \n",
       "Product Specification  ProductDimensions:17x7x10inches|ItemWeight:1.6...   \n",
       "Technical Details      Whether sunning itself on a rock or scurrying ...   \n",
       "Shipping Weight                                               1.6 ounces   \n",
       "Product Dimensions                                                   NaN   \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...   \n",
       "Variants                                                             NaN   \n",
       "Sku                                                                  NaN   \n",
       "Product Url            https://www.amazon.com/Folkmanis-Collared-Liza...   \n",
       "Stock                                                                NaN   \n",
       "Product Details                                                      NaN   \n",
       "Dimensions                                                           NaN   \n",
       "Color                                                                NaN   \n",
       "Ingredients                                                          NaN   \n",
       "Direction To Use                                                     NaN   \n",
       "Is Amazon Seller                                                       Y   \n",
       "Size Quantity Variant                                                NaN   \n",
       "Product Description                                                  NaN   \n",
       "\n",
       "                                                                    1940  \n",
       "Uniq Id                                 7696da17a6ac24c862f0df8017ed8fbf  \n",
       "Product Name           Kids First Engineering Design Physics Lab Scie...  \n",
       "Brand Name                                                           NaN  \n",
       "Asin                                                                 NaN  \n",
       "Category               Toys & Games | Learning & Education | Science ...  \n",
       "Upc Ean Code                                                         NaN  \n",
       "List Price                                                           NaN  \n",
       "Selling Price                                                     $27.99  \n",
       "Quantity                                                             NaN  \n",
       "Model Number                                                      628318  \n",
       "About Product          Make sure this fits by entering your model num...  \n",
       "Product Specification  ProductDimensions:16.8x11.5x3.2inches|ItemWeig...  \n",
       "Technical Details      Go to your orders and start the return Select ...  \n",
       "Shipping Weight                                              2.75 pounds  \n",
       "Product Dimensions                                                   NaN  \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...  \n",
       "Variants                                                             NaN  \n",
       "Sku                                                                  NaN  \n",
       "Product Url            https://www.amazon.com/Kids-First-Engineering-...  \n",
       "Stock                                                                NaN  \n",
       "Product Details                                                      NaN  \n",
       "Dimensions                                                           NaN  \n",
       "Color                                                                NaN  \n",
       "Ingredients                                                          NaN  \n",
       "Direction To Use                                                     NaN  \n",
       "Is Amazon Seller                                                       Y  \n",
       "Size Quantity Variant                                                NaN  \n",
       "Product Description                                                  NaN  "
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataset_df = dataset_df.explode(\"Image\").dropna(subset=[\"Image\"])\n",
    "dataset_df.sample(n=5).T"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Downloading the images\n",
    "\n",
    "We want to create the embeddings out of the images, but we need to have them downloaded in the first place."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:11:55.784129Z",
     "start_time": "2023-07-20T09:11:55.778907Z"
    }
   },
   "outputs": [],
   "source": [
    "from typing import Optional\n",
    "\n",
    "import urllib\n",
    "import os\n",
    "\n",
    "def download_file(url: str) -> Optional[str]:\n",
    "    basename = os.path.basename(url)\n",
    "    target_path = f\"./data/images/{basename}\"\n",
    "    if not os.path.exists(target_path):\n",
    "        try:\n",
    "            urllib.request.urlretrieve(url, target_path)\n",
    "        except urllib.error.HTTPError:\n",
    "            return None\n",
    "    return target_path"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:12:01.589455Z",
     "start_time": "2023-07-20T09:11:55.786290Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>6052</th>\n",
       "      <th>1027</th>\n",
       "      <th>5263</th>\n",
       "      <th>9870</th>\n",
       "      <th>9284</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Uniq Id</th>\n",
       "      <td>96dd5ef14879106d163db214f2230228</td>\n",
       "      <td>40eb9e5884892edc35a550f651dd64f9</td>\n",
       "      <td>441e8894fabb0ee027949036be28adf0</td>\n",
       "      <td>a366b9fe9ebaa14b175fff36323b3f80</td>\n",
       "      <td>e373865ed646dc618d4173e3f5eeb5ea</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Name</th>\n",
       "      <td>B. toys – B. Ready Beach Bag – Beach Tote with...</td>\n",
       "      <td>Kate Aspen Set of 4 Assorted Candle, Whooo's T...</td>\n",
       "      <td>Big Hero 6 The Series Squish-to-Fit Baymax wit...</td>\n",
       "      <td>MightySkins Skin Compatible with Parrot Anafi ...</td>\n",
       "      <td>HANSA Mouse Plush, Brown</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Brand Name</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Asin</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Category</th>\n",
       "      <td>Toys &amp; Games | Sports &amp; Outdoor Play | Pools &amp;...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Toys &amp; Games | Hobbies | Remote &amp; App Controll...</td>\n",
       "      <td>Toys &amp; Games | Stuffed Animals &amp; Plush Toys | ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Upc Ean Code</th>\n",
       "      <td>NaN</td>\n",
       "      <td>843905076882 843905089974</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>List Price</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Selling Price</th>\n",
       "      <td>$23.28</td>\n",
       "      <td>$3.50</td>\n",
       "      <td>$19.99</td>\n",
       "      <td>$19.99</td>\n",
       "      <td>$11.99</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Quantity</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Model Number</th>\n",
       "      <td>BX1307C1Z</td>\n",
       "      <td>20151AS</td>\n",
       "      <td>045557412869</td>\n",
       "      <td>PAANAMIN-Check</td>\n",
       "      <td>190443</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>About Product</th>\n",
       "      <td>Make sure this fits by entering your model num...</td>\n",
       "      <td>Set of four baby owl candle favors in an array...</td>\n",
       "      <td>Make sure this fits by entering your model num...</td>\n",
       "      <td>FLY IN STYLE: Show off your own unique style w...</td>\n",
       "      <td>Make sure this fits by entering your model num...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Specification</th>\n",
       "      <td>ProductDimensions:12x9.5x10inches|ItemWeight:1...</td>\n",
       "      <td>Product Dimensions:         4.1 x 3.6 x 2.5 in...</td>\n",
       "      <td>ProductDimensions:2.5x8x8inches|ItemWeight:15....</td>\n",
       "      <td>ProductDimensions:14x0.1x12inches|ItemWeight:0...</td>\n",
       "      <td>ProductDimensions:4.7x2.4x2.8inches|ItemWeight...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Technical Details</th>\n",
       "      <td>Go to your orders and start the return Select ...</td>\n",
       "      <td>Package Quantity:1 NOTE: This is an assorted p...</td>\n",
       "      <td>Style:Squish-to-Fit Baymax show up to 2 review...</td>\n",
       "      <td>Go to your orders and start the return Select ...</td>\n",
       "      <td>show up to 2 reviews by default HANSA - Brown ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Shipping Weight</th>\n",
       "      <td>2 pounds</td>\n",
       "      <td>9.1 ounces</td>\n",
       "      <td>1 pounds</td>\n",
       "      <td>0.96 ounces</td>\n",
       "      <td>1.12 ounces</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Dimensions</th>\n",
       "      <td>NaN</td>\n",
       "      <td>4.1 x 3.6 x 2.5 inches  5.9 ounces</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Image</th>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Variants</th>\n",
       "      <td>https://www.amazon.com/B-toys-Ready-Beach-Phth...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>https://www.amazon.com/Big-Hero-Squish-Baymax-...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Sku</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Url</th>\n",
       "      <td>https://www.amazon.com/B-toys-Ready-Beach-Phth...</td>\n",
       "      <td>https://www.amazon.com/Kate-Aspen-Assorted-Can...</td>\n",
       "      <td>https://www.amazon.com/Big-Hero-Squish-Baymax-...</td>\n",
       "      <td>https://www.amazon.com/MightySkins-Skin-Parrot...</td>\n",
       "      <td>https://www.amazon.com/Hansa-190443-Mouse-Plus...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Stock</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Details</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Dimensions</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Color</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Ingredients</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Direction To Use</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Is Amazon Seller</th>\n",
       "      <td>Y</td>\n",
       "      <td>Y</td>\n",
       "      <td>Y</td>\n",
       "      <td>Y</td>\n",
       "      <td>Y</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Size Quantity Variant</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Description</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>LocalImage</th>\n",
       "      <td>./data/images/51WSxYeIUPL.jpg</td>\n",
       "      <td>./data/images/41Zm8kpDaUL.jpg</td>\n",
       "      <td>./data/images/41BOXULBG9L.jpg</td>\n",
       "      <td>./data/images/41itUtbTjnL.jpg</td>\n",
       "      <td>./data/images/51JQZhwLmpL.jpg</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                                    6052  \\\n",
       "Uniq Id                                 96dd5ef14879106d163db214f2230228   \n",
       "Product Name           B. toys – B. Ready Beach Bag – Beach Tote with...   \n",
       "Brand Name                                                           NaN   \n",
       "Asin                                                                 NaN   \n",
       "Category               Toys & Games | Sports & Outdoor Play | Pools &...   \n",
       "Upc Ean Code                                                         NaN   \n",
       "List Price                                                           NaN   \n",
       "Selling Price                                                     $23.28   \n",
       "Quantity                                                             NaN   \n",
       "Model Number                                                   BX1307C1Z   \n",
       "About Product          Make sure this fits by entering your model num...   \n",
       "Product Specification  ProductDimensions:12x9.5x10inches|ItemWeight:1...   \n",
       "Technical Details      Go to your orders and start the return Select ...   \n",
       "Shipping Weight                                                 2 pounds   \n",
       "Product Dimensions                                                   NaN   \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...   \n",
       "Variants               https://www.amazon.com/B-toys-Ready-Beach-Phth...   \n",
       "Sku                                                                  NaN   \n",
       "Product Url            https://www.amazon.com/B-toys-Ready-Beach-Phth...   \n",
       "Stock                                                                NaN   \n",
       "Product Details                                                      NaN   \n",
       "Dimensions                                                           NaN   \n",
       "Color                                                                NaN   \n",
       "Ingredients                                                          NaN   \n",
       "Direction To Use                                                     NaN   \n",
       "Is Amazon Seller                                                       Y   \n",
       "Size Quantity Variant                                                NaN   \n",
       "Product Description                                                  NaN   \n",
       "LocalImage                                 ./data/images/51WSxYeIUPL.jpg   \n",
       "\n",
       "                                                                    1027  \\\n",
       "Uniq Id                                 40eb9e5884892edc35a550f651dd64f9   \n",
       "Product Name           Kate Aspen Set of 4 Assorted Candle, Whooo's T...   \n",
       "Brand Name                                                           NaN   \n",
       "Asin                                                                 NaN   \n",
       "Category                                                             NaN   \n",
       "Upc Ean Code                                   843905076882 843905089974   \n",
       "List Price                                                           NaN   \n",
       "Selling Price                                                      $3.50   \n",
       "Quantity                                                             NaN   \n",
       "Model Number                                                     20151AS   \n",
       "About Product          Set of four baby owl candle favors in an array...   \n",
       "Product Specification  Product Dimensions:         4.1 x 3.6 x 2.5 in...   \n",
       "Technical Details      Package Quantity:1 NOTE: This is an assorted p...   \n",
       "Shipping Weight                                               9.1 ounces   \n",
       "Product Dimensions                    4.1 x 3.6 x 2.5 inches  5.9 ounces   \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...   \n",
       "Variants                                                             NaN   \n",
       "Sku                                                                  NaN   \n",
       "Product Url            https://www.amazon.com/Kate-Aspen-Assorted-Can...   \n",
       "Stock                                                                NaN   \n",
       "Product Details                                                      NaN   \n",
       "Dimensions                                                           NaN   \n",
       "Color                                                                NaN   \n",
       "Ingredients                                                          NaN   \n",
       "Direction To Use                                                     NaN   \n",
       "Is Amazon Seller                                                       Y   \n",
       "Size Quantity Variant                                                NaN   \n",
       "Product Description                                                  NaN   \n",
       "LocalImage                                 ./data/images/41Zm8kpDaUL.jpg   \n",
       "\n",
       "                                                                    5263  \\\n",
       "Uniq Id                                 441e8894fabb0ee027949036be28adf0   \n",
       "Product Name           Big Hero 6 The Series Squish-to-Fit Baymax wit...   \n",
       "Brand Name                                                           NaN   \n",
       "Asin                                                                 NaN   \n",
       "Category                                                             NaN   \n",
       "Upc Ean Code                                                         NaN   \n",
       "List Price                                                           NaN   \n",
       "Selling Price                                                     $19.99   \n",
       "Quantity                                                             NaN   \n",
       "Model Number                                                045557412869   \n",
       "About Product          Make sure this fits by entering your model num...   \n",
       "Product Specification  ProductDimensions:2.5x8x8inches|ItemWeight:15....   \n",
       "Technical Details      Style:Squish-to-Fit Baymax show up to 2 review...   \n",
       "Shipping Weight                                                 1 pounds   \n",
       "Product Dimensions                                                   NaN   \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...   \n",
       "Variants               https://www.amazon.com/Big-Hero-Squish-Baymax-...   \n",
       "Sku                                                                  NaN   \n",
       "Product Url            https://www.amazon.com/Big-Hero-Squish-Baymax-...   \n",
       "Stock                                                                NaN   \n",
       "Product Details                                                      NaN   \n",
       "Dimensions                                                           NaN   \n",
       "Color                                                                NaN   \n",
       "Ingredients                                                          NaN   \n",
       "Direction To Use                                                     NaN   \n",
       "Is Amazon Seller                                                       Y   \n",
       "Size Quantity Variant                                                NaN   \n",
       "Product Description                                                  NaN   \n",
       "LocalImage                                 ./data/images/41BOXULBG9L.jpg   \n",
       "\n",
       "                                                                    9870  \\\n",
       "Uniq Id                                 a366b9fe9ebaa14b175fff36323b3f80   \n",
       "Product Name           MightySkins Skin Compatible with Parrot Anafi ...   \n",
       "Brand Name                                                           NaN   \n",
       "Asin                                                                 NaN   \n",
       "Category               Toys & Games | Hobbies | Remote & App Controll...   \n",
       "Upc Ean Code                                                         NaN   \n",
       "List Price                                                           NaN   \n",
       "Selling Price                                                     $19.99   \n",
       "Quantity                                                             NaN   \n",
       "Model Number                                              PAANAMIN-Check   \n",
       "About Product          FLY IN STYLE: Show off your own unique style w...   \n",
       "Product Specification  ProductDimensions:14x0.1x12inches|ItemWeight:0...   \n",
       "Technical Details      Go to your orders and start the return Select ...   \n",
       "Shipping Weight                                              0.96 ounces   \n",
       "Product Dimensions                                                   NaN   \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...   \n",
       "Variants                                                             NaN   \n",
       "Sku                                                                  NaN   \n",
       "Product Url            https://www.amazon.com/MightySkins-Skin-Parrot...   \n",
       "Stock                                                                NaN   \n",
       "Product Details                                                      NaN   \n",
       "Dimensions                                                           NaN   \n",
       "Color                                                                NaN   \n",
       "Ingredients                                                          NaN   \n",
       "Direction To Use                                                     NaN   \n",
       "Is Amazon Seller                                                       Y   \n",
       "Size Quantity Variant                                                NaN   \n",
       "Product Description                                                  NaN   \n",
       "LocalImage                                 ./data/images/41itUtbTjnL.jpg   \n",
       "\n",
       "                                                                    9284  \n",
       "Uniq Id                                 e373865ed646dc618d4173e3f5eeb5ea  \n",
       "Product Name                                    HANSA Mouse Plush, Brown  \n",
       "Brand Name                                                           NaN  \n",
       "Asin                                                                 NaN  \n",
       "Category               Toys & Games | Stuffed Animals & Plush Toys | ...  \n",
       "Upc Ean Code                                                         NaN  \n",
       "List Price                                                           NaN  \n",
       "Selling Price                                                     $11.99  \n",
       "Quantity                                                             NaN  \n",
       "Model Number                                                      190443  \n",
       "About Product          Make sure this fits by entering your model num...  \n",
       "Product Specification  ProductDimensions:4.7x2.4x2.8inches|ItemWeight...  \n",
       "Technical Details      show up to 2 reviews by default HANSA - Brown ...  \n",
       "Shipping Weight                                              1.12 ounces  \n",
       "Product Dimensions                                                   NaN  \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...  \n",
       "Variants                                                             NaN  \n",
       "Sku                                                                  NaN  \n",
       "Product Url            https://www.amazon.com/Hansa-190443-Mouse-Plus...  \n",
       "Stock                                                                NaN  \n",
       "Product Details                                                      NaN  \n",
       "Dimensions                                                           NaN  \n",
       "Color                                                                NaN  \n",
       "Ingredients                                                          NaN  \n",
       "Direction To Use                                                     NaN  \n",
       "Is Amazon Seller                                                       Y  \n",
       "Size Quantity Variant                                                NaN  \n",
       "Product Description                                                  NaN  \n",
       "LocalImage                                 ./data/images/51JQZhwLmpL.jpg  "
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "# Our download_file function returns None in case of any HTTP issues.\n",
    "# We can use that property to filter out the problematic images.\n",
    "dataset_df[\"LocalImage\"] = dataset_df[\"Image\"].map(download_file).replace({None: np.nan})\n",
    "dataset_df = dataset_df.dropna(subset=[\"LocalImage\"])\n",
    "dataset_df.sample(n=5).T"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-06-30T07:02:48.470302Z",
     "start_time": "2023-06-30T07:02:48.470222Z"
    }
   },
   "source": [
    "## Creating the embeddings\n",
    "\n",
    "There are various options for creating the embeddings out of our images. But do not even think about training your neural encoder from scratch! Plenty of pre-trained models are available, and some may already give you some decent results in your domain. And if not, you can use them as a base for the fine-tuning that might be done way faster than the full training.\n",
    "\n",
    "### Available options\n",
    "\n",
    "Using the pretrained models is easy if you choose a library that exposes them with a convenient interface. Some of the possibilities are:\n",
    "\n",
    "- [torchvision](https://pytorch.org/vision/stable/index.html) - part of PyTorch\n",
    "- [embetter](https://koaning.github.io/embetter/) - if you prefer using pandas-like API, that's a great choice\n",
    "- [Sentence-Transformers](https://www.sbert.net/examples/applications/image-search/README.html) - one of the standard libraries for NLP exposes OpenAI CLIP model as well \n",
    "\n",
    "### Choosing the right model\n",
    "\n",
    "If you run an e-commerce business, you probably already have a standard full-text search mechanism. Reverse image search is one option to enrich the user experience, but if you also want to experiment with [hybrid search](https://qdrant.tech/articles/hybrid-search/), you should keep that in mind from the beginning. If that's your scenario, it's better to consider multimodality from day one. Such a model can encode texts and images in the same vector space.\n",
    "\n",
    "For that reason, we are going to use the OpenAI CLIP model, so in the future, we can extend our search mechanism with a semantic search using the same component."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:12:06.155891Z",
     "start_time": "2023-07-20T09:12:01.593671Z"
    }
   },
   "outputs": [],
   "source": [
    "from sentence_transformers import SentenceTransformer\n",
    "from PIL import Image\n",
    "\n",
    "model = SentenceTransformer(\"clip-ViT-B-32\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:12:06.199167Z",
     "start_time": "2023-07-20T09:12:06.157390Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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orlYMpXGS1lkXV3+5tnl1115dHb+abYTGheLLba//frp//blV/8/5/V5g34L6EvLT0wv1tfNtrtqr766ePyP0uJHZg9yPgWt5qJczrHERlKIfPCuCXEP3h8E0lTALkACC7ABLrH53fXzXz578p82q6+ybU5aZgLqzLbLZXKtnzz93ery65NlfnSxTITR3E0pmUwG0ZX6jG6R9fXX/7B58benp5uPHj1KaQPaxhs0n6blJ0u/6PvcNAvKW3RoFn/zt/9OsB/86BcPz2nNb7fbb+jNcnG+ODn55ee/udysTs6b5flF58mtY1r/6h/+/Wr7bPng4fLk0dky0Xom5Pb0waOPLlcvnj//qxeXV+v1enHyVXv647Pzz7g4AxoA8xVUd08p3fEmBcH9EOIevE9MMhIUvIjWgxvomV/9+ovf/aX6L73/+qS5PmmxSISrlEJYt+4ur55dPn/epPbx4w/OTh6WYr1Tyu4JSl5bTZ209RdP/+aLJ/9W69+kx+mk8d59u15ed2cPP/qZnfz8YvFZh0zrydXq6je/++aLS1989vGPPvv052j67Qu/6nTSfrh48KP11VZ2dv6wX1581qVH185N/+zy+ecvoAef/OLjs49O8gMrmb0Da3Bj2G5XX3p52i5alMX26rL0TzbXX7UXf7w4+6RtWoI+JtwjORO8B0Lcg/eKqtmAQBLWA8+w/punX//71bO/O2n70wWyZZX1ttu0hsXCUl48ffLV9bOvW+Lxg0cPzx8BzfVWKTXuGZYhGgu5JdbGq7/65f/WbX5zlvpN1z+9GmweN970PKGWvRabbe+8bvPV1eqrz3/7dz/64Z8/uvgElnH9dLPZWmrZnBVvf/3F85OLH3/yow96WUEht/LffvXF3yyXj84e/PThox+wtNhatoSy2W6ffPXN3z193p9enH/y4YeWFlfX627z+dXl1bZzQ2kfPQIy/MRpNOMUxYctcPDOCHEP3itCcdYCGRAb+OfPvvpXV0/+6uEimWWWM/cFLTGTeWV2ubr+9erymyR8+PCj04tH8KSiZbPcOIq87zqynJ74orm8vvy7J1/+/cMTP3302fmytHkNbYXE9PgsfdpeNMibzn+77S779RdbPUnlq598aB+ePsi2hF4gX12cNX23eHH95Osvrkr7sLl40PFCvuk3n5ftl1z93Ue5f/z4vzw//VESu/JCaZsa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EARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcISEuAdBEBwhIe5BEARHSIh7EATBERLiHgRBcIT8/wHiAl7DID9TiwAAAABJRU5ErkJggg==",
      "text/plain": [
       "<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=500x500 at 0x7F64C21C1870>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "image = Image.open(dataset_df.iloc[0][\"LocalImage\"])\n",
    "image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:12:08.382103Z",
     "start_time": "2023-07-20T09:12:06.202918Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(512,)"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "image_embedding = model.encode(image)\n",
    "image_embedding.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:12:08.391751Z",
     "start_time": "2023-07-20T09:12:08.383699Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-7.70826563e-02,  2.47614056e-01, -1.88366160e-01,  3.77686061e-02,\n",
       "        2.75502801e-01, -1.17113851e-01,  2.19550878e-01,  5.89040875e-01,\n",
       "       -4.67717290e-01,  6.99918926e-01, -1.50128081e-01,  1.62355796e-01,\n",
       "        2.19392225e-01,  3.03609788e-01,  3.69749725e-01, -1.64401203e-01,\n",
       "        7.73335218e-01,  3.57864857e-01, -3.12968254e-01, -4.61788267e-01,\n",
       "       -4.92363334e-01, -8.49841535e-02, -8.51628184e-02,  3.20015669e-01,\n",
       "       -2.52207518e-01,  2.32379332e-01,  4.86825667e-02, -1.42236590e-01,\n",
       "       -1.60141245e-01, -2.28923053e-01, -1.32132262e-01,  4.20752674e-01,\n",
       "       -2.31687710e-01,  3.00777495e-01, -7.94995725e-02, -2.03304872e-01,\n",
       "       -2.90620863e-01,  1.13647804e-02, -4.52846527e-01,  8.38866532e-02,\n",
       "        2.70952940e-01, -3.34870994e-01,  6.76658750e-02, -2.44590312e-01,\n",
       "        1.06996298e-01, -1.84915113e+00,  8.02336633e-03,  6.95288554e-02,\n",
       "       -4.07707505e-02, -4.37983245e-01,  2.68795818e-01,  2.36790076e-01,\n",
       "        3.60334724e-01, -4.72699285e-01, -4.27086204e-01,  2.54274726e-01,\n",
       "       -2.56275147e-01, -3.73525113e-01,  6.09452307e-01,  3.80056739e-01,\n",
       "        6.61989689e-01, -4.49292064e-01,  2.58101195e-01,  4.49719757e-01,\n",
       "       -3.75585258e-03, -2.13872418e-02,  6.53526902e-01,  3.65155756e-01,\n",
       "       -1.93988517e-01,  8.38487595e-03, -5.82983851e-01, -5.71574688e-01,\n",
       "       -2.32030362e-01, -4.14538115e-01,  8.64695758e-04, -9.84336510e-02,\n",
       "        1.14891395e-01, -1.35332361e-01, -1.50024518e-01,  1.78963721e-01,\n",
       "        2.42739961e-01, -1.62889600e-01, -6.08754396e-01, -8.03908527e-01,\n",
       "       -2.02127054e-01, -2.73267895e-01,  7.14197993e-01,  1.79633379e-01,\n",
       "       -4.40025091e-01, -4.94036168e-01,  5.83944619e-01,  5.64683527e-02,\n",
       "       -6.94801855e+00, -1.48649886e-01, -1.72202349e-01,  2.40936965e-01,\n",
       "        4.49336737e-01,  3.84209275e-01, -2.38307923e-01,  7.07096279e-01,\n",
       "        2.98210531e-01, -6.64537251e-01,  6.80880100e-02,  2.68124014e-01,\n",
       "       -1.82074308e-01, -6.28862977e-02, -1.70366371e+00, -5.36886454e-01,\n",
       "        4.23195034e-01,  6.77088276e-03, -2.48027995e-01,  3.11396033e-01,\n",
       "        1.60204142e-01,  1.11834072e-02, -3.31723094e-01, -1.58816189e-01,\n",
       "        2.09409788e-01, -5.17414212e-02, -7.62796625e-02, -1.70487702e-01,\n",
       "        2.19435424e-01,  3.53272200e-01,  8.45223293e-02, -3.27509522e-01,\n",
       "        2.33615823e-02,  3.89695406e-01, -3.16450089e-01,  6.40980154e-02,\n",
       "        1.58968240e-01, -1.92113593e-01, -2.14382023e-01,  4.10529822e-01,\n",
       "        2.18840688e-01,  9.02656436e-01,  4.00709093e-01,  2.32551470e-02,\n",
       "       -3.74677211e-01, -1.83924258e-01, -2.85019219e-01, -2.08735943e-01,\n",
       "       -9.37712640e-02, -1.50819793e-01, -4.90050852e-01, -1.25337854e-01,\n",
       "       -3.18297565e-01, -3.14687431e-01,  1.04413621e-01,  1.14113189e-01,\n",
       "       -1.22878335e-01, -2.10647389e-01,  2.63605453e-02, -4.35284674e-01,\n",
       "        3.40047807e-01, -5.25459588e-01, -2.01964378e-01, -3.13811779e-01,\n",
       "       -7.47599155e-02, -2.29829490e-01,  7.54747540e-03, -2.46410295e-02,\n",
       "       -1.12191074e-01,  1.70214951e-01,  4.73940760e-01, -4.79729354e-01,\n",
       "        9.78194922e-02,  1.56981871e-03, -3.59271556e-01, -1.04255937e-01,\n",
       "        5.20155430e-01,  3.88195843e-01,  1.84849411e-01, -9.03039873e-02,\n",
       "        3.03762555e-01,  2.51973867e-01, -2.85194933e-01,  1.79504573e-01,\n",
       "        5.20015776e-01, -6.76068813e-02,  9.83394444e-01, -3.25285494e-02,\n",
       "        5.74509084e-01,  1.33793756e-01,  2.10332990e-01, -2.11818278e-01,\n",
       "       -1.21672153e-01,  5.76796792e-02,  1.78325564e-01, -3.33588362e-01,\n",
       "        7.76048750e-03,  1.77861005e-01,  2.50764847e-01, -1.37617260e-01,\n",
       "       -1.74975172e-01, -3.99722904e-01,  4.00222659e-01, -8.33427757e-02,\n",
       "        4.52680290e-02, -6.88257396e-01, -3.14554632e-01,  1.48542240e-01,\n",
       "       -1.43017381e-01, -3.87580454e-01, -3.74805272e-01,  3.85639429e-01,\n",
       "        2.99779713e-01, -2.12634087e-01, -2.20324457e-01, -3.59686255e-01,\n",
       "        6.44048899e-02, -2.49437332e-01, -5.61883971e-02,  5.14398336e-01,\n",
       "       -2.79619008e-01,  6.32114783e-02,  1.35709852e-01, -3.39364260e-03,\n",
       "        3.60346168e-01,  3.02594081e-02, -1.93180263e-01, -2.00695544e-03,\n",
       "        4.56569314e-01, -4.31873441e-01, -1.75015181e-01,  1.40962213e-01,\n",
       "       -1.26997486e-01,  3.82957458e-01, -7.42759824e-01,  1.75637752e-01,\n",
       "       -5.91126084e-02, -8.38991702e-02,  2.47630566e-01, -1.26985952e-01,\n",
       "        2.60879695e-01, -4.67866957e-02,  3.72194171e-01,  4.14674073e-01,\n",
       "        3.85815829e-01, -2.73556441e-01, -2.54055619e-01,  1.05604425e-01,\n",
       "       -6.89110532e-03,  5.05796313e-01, -7.88211152e-02, -5.55839181e-01,\n",
       "       -8.55627060e-02, -1.12791725e-01, -6.67609200e-02,  8.83903444e-01,\n",
       "        2.30129570e-01,  1.91034839e-01, -5.11519313e-02, -3.23076189e-01,\n",
       "       -6.69024512e-02,  2.94394553e-01,  2.95460343e-01,  1.32120922e-01,\n",
       "       -1.86843947e-01,  3.95881981e-01, -3.30369920e-02,  2.62350857e-01,\n",
       "        1.36975810e-01, -9.21172872e-02, -1.90769702e-01,  1.72109276e-01,\n",
       "       -8.78537893e-02,  4.23703462e-01, -8.19969177e-03, -4.12617743e-01,\n",
       "       -2.31835976e-01,  2.77337760e-01,  2.40354121e-01,  2.33174115e-01,\n",
       "        2.21125633e-01,  3.10812801e-01,  4.05021191e-01,  4.04821932e-02,\n",
       "       -2.68143058e-01, -2.48994306e-01, -3.65828007e-01,  5.99115118e-02,\n",
       "       -4.34370309e-01,  4.16762143e-01, -6.15916252e-01, -4.11352158e-01,\n",
       "        5.82373142e-03,  1.67124957e-01,  1.71123409e+00, -1.36223257e-01,\n",
       "        1.66319966e-01,  9.24832448e-02,  4.20724750e-01, -2.47349709e-01,\n",
       "       -6.30005360e-01, -4.83090691e-02,  3.73189412e-02, -1.40901938e-01,\n",
       "       -4.02421355e-01, -7.64831156e-03,  5.08170605e-01, -8.52315649e-02,\n",
       "       -3.15860927e-01, -5.40655434e-01, -3.56036946e-02,  9.17736739e-02,\n",
       "       -2.70996034e-01, -6.48129225e-01,  4.84871492e-02, -1.41832501e-01,\n",
       "        1.58846587e-01,  1.78017050e-01, -1.56525806e-01,  3.88337284e-01,\n",
       "        9.02757943e-01, -3.15833658e-01,  1.16797321e-01,  4.66010571e-02,\n",
       "        4.06989098e-01, -1.10471815e-01,  1.24812946e-02, -4.87099230e-01,\n",
       "        2.58042574e-01,  2.72807884e+00,  1.19536892e-01, -1.36719361e-01,\n",
       "       -1.18068792e-01, -4.70690578e-02,  1.75217494e-01,  1.20094106e-01,\n",
       "       -4.45067436e-01,  1.88191310e-01,  1.61280483e-01,  2.15195403e-01,\n",
       "        4.53405738e-01, -3.96829844e-01, -7.36266896e-02,  9.85634178e-02,\n",
       "        3.98397222e-02,  2.07955375e-01, -2.52954960e-01,  7.15883076e-03,\n",
       "       -3.17317173e-02, -3.48367356e-02,  1.16920397e-01,  3.57286297e-02,\n",
       "        7.96121135e-02,  2.55063862e-01,  6.92925215e-01,  9.82059389e-02,\n",
       "       -3.05361971e-02, -4.16356057e-01, -2.18569860e-02,  4.55428064e-01,\n",
       "        3.79489630e-01, -3.69095713e-01,  4.54952955e-01, -2.83336818e-01,\n",
       "       -2.07771629e-01, -1.41506135e-01,  2.12518424e-01, -4.29747224e-01,\n",
       "        1.30583212e-01, -6.14102185e-01,  1.39680490e-01, -3.59357864e-01,\n",
       "       -2.35923484e-01, -4.10463661e-03,  4.32046622e-01,  3.95074338e-01,\n",
       "       -2.13442221e-01, -5.20557940e-01, -6.99962497e-01, -1.47700384e-01,\n",
       "       -2.19327003e-01,  1.18096679e-01,  3.23297709e-01, -1.35628045e-01,\n",
       "        4.44667220e-01, -1.17392465e-02, -2.75935560e-01,  6.88298643e-02,\n",
       "       -3.46671008e-02, -2.93675244e-01, -2.54007757e-01, -3.79927754e-02,\n",
       "       -6.99370503e-02,  2.82531679e-01, -1.81477517e-02, -7.51476884e-02,\n",
       "        1.06913477e-01,  6.14787489e-02, -1.04238844e+00, -2.89158434e-01,\n",
       "        2.85871089e-01, -4.17681873e-01, -4.36652422e-01,  1.02241144e-01,\n",
       "        4.19407725e-01, -2.05078214e-01,  5.85912228e-01, -9.84846279e-02,\n",
       "        2.14297846e-01,  7.90149197e-02,  5.51783681e-01, -1.87467501e-01,\n",
       "       -5.50519764e-01, -3.06408912e-01, -1.26905039e-01,  1.84982732e-01,\n",
       "        8.19279850e-01, -1.40260011e-01,  3.34040999e-01, -1.88807547e-01,\n",
       "        1.54898509e-01,  6.16540194e-01, -2.80969560e-01,  3.71864825e-01,\n",
       "       -3.08403552e-01,  9.76056993e-01, -3.61614585e-01, -1.89213693e-01,\n",
       "       -1.15244344e-01, -1.36035793e-02, -1.42821163e-01, -1.85743138e-01,\n",
       "        2.92974591e-01,  6.83899596e-03, -5.56827150e-02, -1.25176266e-01,\n",
       "       -2.32924318e+00, -3.60146463e-02, -1.93035975e-02, -4.53288913e-01,\n",
       "        5.63881218e-01, -1.46725893e-01, -5.18512666e-01, -2.68946022e-01,\n",
       "        1.51954606e-01, -1.34081647e-01,  6.25258014e-02, -4.53493416e-01,\n",
       "       -1.03577748e-02,  3.53248119e-01, -1.28228113e-01,  4.51895028e-01,\n",
       "       -2.25224748e-01,  9.80474949e-02,  1.77896068e-01, -5.40967099e-03,\n",
       "       -1.57206319e-02, -6.57768771e-02,  5.97743392e-01,  1.30120859e-01,\n",
       "        4.48920637e-01, -9.13060308e-01,  7.78545216e-02,  2.40753964e-03,\n",
       "       -4.14288253e-01, -1.90064698e-01,  4.30256546e-01, -3.46881986e-01,\n",
       "        1.58129036e-01,  1.81515530e-01,  2.32051551e-01,  1.31825000e-01,\n",
       "        7.16098070e-01,  2.57443368e-01,  1.39437526e-01,  3.23809907e-02,\n",
       "       -1.92752540e-01, -1.50489300e-01, -2.54649892e-02, -7.83468187e-02,\n",
       "        1.63895726e-01, -2.69670039e-04,  5.47546893e-03,  1.09126329e-01,\n",
       "       -1.58701673e-01,  1.22555718e-01, -6.35729134e-02, -1.52891159e-01,\n",
       "       -2.46589273e-01, -1.29782557e-01,  1.52134776e-01, -4.22351435e-03,\n",
       "       -1.95206180e-01,  5.11216521e-01,  3.19093287e-01,  2.16117531e-01,\n",
       "        1.20604634e-01, -2.93606400e-01,  2.01510340e-01,  2.70424113e-02,\n",
       "        3.99051785e-01,  8.87436494e-02, -3.86849552e-01, -1.16143242e-01,\n",
       "        2.33300269e-01, -4.80542965e-02, -5.13781607e-02,  2.14840382e-01,\n",
       "       -1.29578710e-01, -8.48059580e-02,  2.06116915e-01, -8.07906240e-02,\n",
       "        1.56389162e-01, -3.07766557e-01, -1.39300525e-02,  1.79486245e-01,\n",
       "        8.84139687e-02,  6.27903163e-01,  2.38037333e-01, -8.46069530e-02],\n",
       "      dtype=float32)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "image_embedding"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "That's what a single embedding look like. But we need to calculate them for each image in our dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:12:08.439328Z",
     "start_time": "2023-07-20T09:12:08.393561Z"
    }
   },
   "outputs": [],
   "source": [
    "from typing import List\n",
    "\n",
    "def calculate_embedding(image_path: str) -> Optional[List[float]]:\n",
    "    try:\n",
    "        image = Image.open(image_path)\n",
    "        return model.encode(image).tolist()\n",
    "    except:\n",
    "        return None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:14:43.715687Z",
     "start_time": "2023-07-20T09:12:08.442647Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>3543</th>\n",
       "      <th>3977</th>\n",
       "      <th>5215</th>\n",
       "      <th>8142</th>\n",
       "      <th>2616</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Uniq Id</th>\n",
       "      <td>f86d8eef75a99249738afc6abd05535c</td>\n",
       "      <td>7a4ee68c3e20ed02195f676f8001c85d</td>\n",
       "      <td>ef2a1317812b5f7f05e0df3f2559374c</td>\n",
       "      <td>fac450e9f7ab002cf6c60f26044cfc4f</td>\n",
       "      <td>8408822d462b23e057582315adb983dd</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Name</th>\n",
       "      <td>SCHLEICH North America Showjumper with Horse F...</td>\n",
       "      <td>Rubie's Justice League Movie Child's Superman ...</td>\n",
       "      <td>Circuit Cubes Bright Lights STEM Toy Lego Comp...</td>\n",
       "      <td>MightySkins Skin Compatible with Swagtron Swag...</td>\n",
       "      <td>Energen DroneMax MA18A Drone Battery Charger, ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Brand Name</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Asin</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Category</th>\n",
       "      <td>Toys &amp; Games | Toy Figures &amp; Playsets | Playse...</td>\n",
       "      <td>Clothing, Shoes &amp; Jewelry | Costumes &amp; Accesso...</td>\n",
       "      <td>Toys &amp; Games | Learning &amp; Education | Science ...</td>\n",
       "      <td>Sports &amp; Outdoors | Outdoor Recreation | Skate...</td>\n",
       "      <td>Toys &amp; Games | Hobbies | Remote &amp; App Controll...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Upc Ean Code</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>List Price</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Selling Price</th>\n",
       "      <td>$19.99</td>\n",
       "      <td>$28.46 - $37.99</td>\n",
       "      <td>$19.10</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$49.99</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Quantity</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Model Number</th>\n",
       "      <td>42358</td>\n",
       "      <td>NaN</td>\n",
       "      <td>11021-0000</td>\n",
       "      <td>SWSD15-Flower Wheels</td>\n",
       "      <td>EN-DM-MA18A</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>About Product</th>\n",
       "      <td>Make sure this fits by entering your model num...</td>\n",
       "      <td>Polyester | Includes: Jumpsuit With Attached M...</td>\n",
       "      <td>Make sure this fits by entering your model num...</td>\n",
       "      <td>FLY IN STLYE: Show off your own unique style w...</td>\n",
       "      <td>Make sure this fits by entering your model num...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Specification</th>\n",
       "      <td>ProductDimensions:3.4x5.9x7.1inches|ItemWeight...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>ProductDimensions:6x1.5x2inches|ItemWeight:1.3...</td>\n",
       "      <td>ProductDimensions:9x0.1x6inches|ItemWeight:0.1...</td>\n",
       "      <td>Product Dimensions:         6.7 x 4.5 x 1.8 in...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Technical Details</th>\n",
       "      <td>All Schleich figures are lovingly hand-painted...</td>\n",
       "      <td>It�s a bird, it�s a plane, no it�s your little...</td>\n",
       "      <td>Product Description Young scientists, engineer...</td>\n",
       "      <td>show up to 2 reviews by default Do You Want Yo...</td>\n",
       "      <td>Go to your orders and start the return Select ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Shipping Weight</th>\n",
       "      <td>7.2 ounces</td>\n",
       "      <td>1.03 pounds</td>\n",
       "      <td>1.3 pounds</td>\n",
       "      <td>0.96 ounces</td>\n",
       "      <td>1.8 pounds</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Dimensions</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>6.7 x 4.5 x 1.8 inches  1.3 pounds</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Image</th>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "      <td>https://images-na.ssl-images-amazon.com/images...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Variants</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>https://www.amazon.com/Energen-Accessories-Int...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Sku</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Url</th>\n",
       "      <td>https://www.amazon.com/Schleich-North-America-...</td>\n",
       "      <td>https://www.amazon.com/Rubies-Justice-Superman...</td>\n",
       "      <td>https://www.amazon.com/Circuit-Cubes-Compatibl...</td>\n",
       "      <td>https://www.amazon.com/MightySkins-Skin-Swagtr...</td>\n",
       "      <td>https://www.amazon.com/Energen-Accessories-Int...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Stock</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Details</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Dimensions</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Color</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Ingredients</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Direction To Use</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Is Amazon Seller</th>\n",
       "      <td>Y</td>\n",
       "      <td>Y</td>\n",
       "      <td>Y</td>\n",
       "      <td>N</td>\n",
       "      <td>Y</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Size Quantity Variant</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product Description</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>LocalImage</th>\n",
       "      <td>./data/images/51uHd6GsExL.jpg</td>\n",
       "      <td>./data/images/51ZwQkLFwbL.jpg</td>\n",
       "      <td>./data/images/5121Pq8imNL.jpg</td>\n",
       "      <td>./data/images/51gUNvbCYhL.jpg</td>\n",
       "      <td>./data/images/51OAmIpsKyL.jpg</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Embedding</th>\n",
       "      <td>[0.07704341411590576, 0.09430709481239319, -0....</td>\n",
       "      <td>[-0.2711644172668457, 0.4122364819049835, -0.3...</td>\n",
       "      <td>[-0.038734789937734604, 0.03277008235454559, 0...</td>\n",
       "      <td>[0.635156512260437, -0.34147804975509644, -0.0...</td>\n",
       "      <td>[-0.6532032489776611, 0.29867327213287354, 0.0...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                                    3543  \\\n",
       "Uniq Id                                 f86d8eef75a99249738afc6abd05535c   \n",
       "Product Name           SCHLEICH North America Showjumper with Horse F...   \n",
       "Brand Name                                                           NaN   \n",
       "Asin                                                                 NaN   \n",
       "Category               Toys & Games | Toy Figures & Playsets | Playse...   \n",
       "Upc Ean Code                                                         NaN   \n",
       "List Price                                                           NaN   \n",
       "Selling Price                                                     $19.99   \n",
       "Quantity                                                             NaN   \n",
       "Model Number                                                       42358   \n",
       "About Product          Make sure this fits by entering your model num...   \n",
       "Product Specification  ProductDimensions:3.4x5.9x7.1inches|ItemWeight...   \n",
       "Technical Details      All Schleich figures are lovingly hand-painted...   \n",
       "Shipping Weight                                               7.2 ounces   \n",
       "Product Dimensions                                                   NaN   \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...   \n",
       "Variants                                                             NaN   \n",
       "Sku                                                                  NaN   \n",
       "Product Url            https://www.amazon.com/Schleich-North-America-...   \n",
       "Stock                                                                NaN   \n",
       "Product Details                                                      NaN   \n",
       "Dimensions                                                           NaN   \n",
       "Color                                                                NaN   \n",
       "Ingredients                                                          NaN   \n",
       "Direction To Use                                                     NaN   \n",
       "Is Amazon Seller                                                       Y   \n",
       "Size Quantity Variant                                                NaN   \n",
       "Product Description                                                  NaN   \n",
       "LocalImage                                 ./data/images/51uHd6GsExL.jpg   \n",
       "Embedding              [0.07704341411590576, 0.09430709481239319, -0....   \n",
       "\n",
       "                                                                    3977  \\\n",
       "Uniq Id                                 7a4ee68c3e20ed02195f676f8001c85d   \n",
       "Product Name           Rubie's Justice League Movie Child's Superman ...   \n",
       "Brand Name                                                           NaN   \n",
       "Asin                                                                 NaN   \n",
       "Category               Clothing, Shoes & Jewelry | Costumes & Accesso...   \n",
       "Upc Ean Code                                                         NaN   \n",
       "List Price                                                           NaN   \n",
       "Selling Price                                            $28.46 - $37.99   \n",
       "Quantity                                                             NaN   \n",
       "Model Number                                                         NaN   \n",
       "About Product          Polyester | Includes: Jumpsuit With Attached M...   \n",
       "Product Specification                                                NaN   \n",
       "Technical Details      It�s a bird, it�s a plane, no it�s your little...   \n",
       "Shipping Weight                                              1.03 pounds   \n",
       "Product Dimensions                                                   NaN   \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...   \n",
       "Variants                                                             NaN   \n",
       "Sku                                                                  NaN   \n",
       "Product Url            https://www.amazon.com/Rubies-Justice-Superman...   \n",
       "Stock                                                                NaN   \n",
       "Product Details                                                      NaN   \n",
       "Dimensions                                                           NaN   \n",
       "Color                                                                NaN   \n",
       "Ingredients                                                          NaN   \n",
       "Direction To Use                                                     NaN   \n",
       "Is Amazon Seller                                                       Y   \n",
       "Size Quantity Variant                                                NaN   \n",
       "Product Description                                                  NaN   \n",
       "LocalImage                                 ./data/images/51ZwQkLFwbL.jpg   \n",
       "Embedding              [-0.2711644172668457, 0.4122364819049835, -0.3...   \n",
       "\n",
       "                                                                    5215  \\\n",
       "Uniq Id                                 ef2a1317812b5f7f05e0df3f2559374c   \n",
       "Product Name           Circuit Cubes Bright Lights STEM Toy Lego Comp...   \n",
       "Brand Name                                                           NaN   \n",
       "Asin                                                                 NaN   \n",
       "Category               Toys & Games | Learning & Education | Science ...   \n",
       "Upc Ean Code                                                         NaN   \n",
       "List Price                                                           NaN   \n",
       "Selling Price                                                     $19.10   \n",
       "Quantity                                                             NaN   \n",
       "Model Number                                                  11021-0000   \n",
       "About Product          Make sure this fits by entering your model num...   \n",
       "Product Specification  ProductDimensions:6x1.5x2inches|ItemWeight:1.3...   \n",
       "Technical Details      Product Description Young scientists, engineer...   \n",
       "Shipping Weight                                               1.3 pounds   \n",
       "Product Dimensions                                                   NaN   \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...   \n",
       "Variants                                                             NaN   \n",
       "Sku                                                                  NaN   \n",
       "Product Url            https://www.amazon.com/Circuit-Cubes-Compatibl...   \n",
       "Stock                                                                NaN   \n",
       "Product Details                                                      NaN   \n",
       "Dimensions                                                           NaN   \n",
       "Color                                                                NaN   \n",
       "Ingredients                                                          NaN   \n",
       "Direction To Use                                                     NaN   \n",
       "Is Amazon Seller                                                       Y   \n",
       "Size Quantity Variant                                                NaN   \n",
       "Product Description                                                  NaN   \n",
       "LocalImage                                 ./data/images/5121Pq8imNL.jpg   \n",
       "Embedding              [-0.038734789937734604, 0.03277008235454559, 0...   \n",
       "\n",
       "                                                                    8142  \\\n",
       "Uniq Id                                 fac450e9f7ab002cf6c60f26044cfc4f   \n",
       "Product Name           MightySkins Skin Compatible with Swagtron Swag...   \n",
       "Brand Name                                                           NaN   \n",
       "Asin                                                                 NaN   \n",
       "Category               Sports & Outdoors | Outdoor Recreation | Skate...   \n",
       "Upc Ean Code                                                         NaN   \n",
       "List Price                                                           NaN   \n",
       "Selling Price                                                        NaN   \n",
       "Quantity                                                             NaN   \n",
       "Model Number                                        SWSD15-Flower Wheels   \n",
       "About Product          FLY IN STLYE: Show off your own unique style w...   \n",
       "Product Specification  ProductDimensions:9x0.1x6inches|ItemWeight:0.1...   \n",
       "Technical Details      show up to 2 reviews by default Do You Want Yo...   \n",
       "Shipping Weight                                              0.96 ounces   \n",
       "Product Dimensions                                                   NaN   \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...   \n",
       "Variants                                                             NaN   \n",
       "Sku                                                                  NaN   \n",
       "Product Url            https://www.amazon.com/MightySkins-Skin-Swagtr...   \n",
       "Stock                                                                NaN   \n",
       "Product Details                                                      NaN   \n",
       "Dimensions                                                           NaN   \n",
       "Color                                                                NaN   \n",
       "Ingredients                                                          NaN   \n",
       "Direction To Use                                                     NaN   \n",
       "Is Amazon Seller                                                       N   \n",
       "Size Quantity Variant                                                NaN   \n",
       "Product Description                                                  NaN   \n",
       "LocalImage                                 ./data/images/51gUNvbCYhL.jpg   \n",
       "Embedding              [0.635156512260437, -0.34147804975509644, -0.0...   \n",
       "\n",
       "                                                                    2616  \n",
       "Uniq Id                                 8408822d462b23e057582315adb983dd  \n",
       "Product Name           Energen DroneMax MA18A Drone Battery Charger, ...  \n",
       "Brand Name                                                           NaN  \n",
       "Asin                                                                 NaN  \n",
       "Category               Toys & Games | Hobbies | Remote & App Controll...  \n",
       "Upc Ean Code                                                         NaN  \n",
       "List Price                                                           NaN  \n",
       "Selling Price                                                     $49.99  \n",
       "Quantity                                                             NaN  \n",
       "Model Number                                                 EN-DM-MA18A  \n",
       "About Product          Make sure this fits by entering your model num...  \n",
       "Product Specification  Product Dimensions:         6.7 x 4.5 x 1.8 in...  \n",
       "Technical Details      Go to your orders and start the return Select ...  \n",
       "Shipping Weight                                               1.8 pounds  \n",
       "Product Dimensions                    6.7 x 4.5 x 1.8 inches  1.3 pounds  \n",
       "Image                  https://images-na.ssl-images-amazon.com/images...  \n",
       "Variants               https://www.amazon.com/Energen-Accessories-Int...  \n",
       "Sku                                                                  NaN  \n",
       "Product Url            https://www.amazon.com/Energen-Accessories-Int...  \n",
       "Stock                                                                NaN  \n",
       "Product Details                                                      NaN  \n",
       "Dimensions                                                           NaN  \n",
       "Color                                                                NaN  \n",
       "Ingredients                                                          NaN  \n",
       "Direction To Use                                                     NaN  \n",
       "Is Amazon Seller                                                       Y  \n",
       "Size Quantity Variant                                                NaN  \n",
       "Product Description                                                  NaN  \n",
       "LocalImage                                 ./data/images/51OAmIpsKyL.jpg  \n",
       "Embedding              [-0.6532032489776611, 0.29867327213287354, 0.0...  "
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Again, our helper function returns None in case of any error, such as\n",
    "# unsupported image format. We need to remove those entries.\n",
    "dataset_df[\"Embedding\"] = dataset_df[\"LocalImage\"].map(calculate_embedding)\n",
    "dataset_df[\"Embedding\"] = dataset_df[\"Embedding\"].replace({None: np.nan})\n",
    "dataset_df = dataset_df.dropna(subset=[\"Embedding\"])\n",
    "dataset_df.sample(n=5).T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:14:44.118177Z",
     "start_time": "2023-07-20T09:14:43.717833Z"
    }
   },
   "outputs": [],
   "source": [
    "dataset_df.to_parquet(\"./data/amazon-with-embeddings.parquet\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Indexing embeddings in Qdrant\n",
    "\n",
    "Reverse image search compares the embeddings of the image used as a query and the embeddings of the indexed pictures. That can be theoretically done in a naive way by comparing the query to every single item from our store, but that won't scale if we even go beyond a few hundred. That's what the vector search engines are designed for. Qdrant acts as a fast retrieval layer that performs an efficient search for the closest vectors in the space.\n",
    "\n",
    "There are various ways to start using Qdrant, and even though the local mode in Python SDK is possible, it should be running as a service in production. The easiest way is to use a Docker container, which we'll do."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:14:45.419964Z",
     "start_time": "2023-07-20T09:14:44.121336Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9c03f57d7060ea4f5d5b13a0d027f20005ed92443aa975513170a7225c72eec9\r\n"
     ]
    }
   ],
   "source": [
    "!docker run -d -p \"6333:6333\" -p \"6334:6334\" --name \"reverse_image_search\" qdrant/qdrant:v1.3.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:14:45.975516Z",
     "start_time": "2023-07-20T09:14:45.425849Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "CollectionsResponse(collections=[])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from qdrant_client import QdrantClient\n",
    "from qdrant_client.http import models as rest\n",
    "\n",
    "try:\n",
    "    client = QdrantClient(\"localhost\")\n",
    "    collections = client.get_collections()\n",
    "except Exception:\n",
    "    # Docker is unavailable in Google Colab so we switch to local\n",
    "    # mode available in Python SDK\n",
    "    client = QdrantClient(\":memory:\")\n",
    "    collections = client.get_collections()\n",
    "\n",
    "collections"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:14:46.478406Z",
     "start_time": "2023-07-20T09:14:45.978171Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "client.recreate_collection(\n",
    "    collection_name=\"amazon\",\n",
    "    vectors_config=rest.VectorParams(\n",
    "        size=512,\n",
    "        distance=rest.Distance.COSINE,\n",
    "    )\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It's a good practice to use batching while inserting the vectors into the collection. Python SDK has a utility method that performs it automatically. For the purposes of our demo, we're going to store vectors with the product id, name, and description as a payload."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:14:46.513789Z",
     "start_time": "2023-07-20T09:14:46.479733Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'ID': '46ef101b598f2fff7037c44a9a18c402',\n",
       " 'Name': 'LEGO Round Storage Box 1, Yellow',\n",
       " 'Description': 'Make sure this fits by entering your model number. | Have fun while staying organized. | Recommended for Ages 3+ | Other Colors and Sizes available | Makes for the perfect gift!! | Small size round lego storage bin | Plastic - polypropylene (pp), pvc free | Gather all your regular lego bricks in this small size round storage bin and make it a more playful way of tidying up | This small size round LEGO storage box also works as a stackable block with the rest of the storage bricks | Storage blocks come in classic lego colors',\n",
       " 'Image': 'https://images-na.ssl-images-amazon.com/images/I/21ibn-69NWL.jpg',\n",
       " 'Path': './data/images/21ibn-69NWL.jpg'}"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "payloads = dataset_df[[\"Uniq Id\", \"Product Name\", \"About Product\", \"Image\", \"LocalImage\"]] \\\n",
    "    .fillna(\"Unknown\") \\\n",
    "    .rename(columns={\"Uniq Id\": \"ID\", \n",
    "                     \"Product Name\": \"Name\", \n",
    "                     \"About Product\": \"Description\",\n",
    "                     \"LocalImage\": \"Path\"}) \\\n",
    "    .to_dict(\"records\")\n",
    "payloads[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:15:11.503216Z",
     "start_time": "2023-07-20T09:14:46.515774Z"
    },
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "import uuid\n",
    "\n",
    "client.upload_collection(\n",
    "    collection_name=\"amazon\",\n",
    "    vectors=list(map(list, dataset_df[\"Embedding\"].tolist())),\n",
    "    payload=payloads,\n",
    "    ids=[uuid.uuid4().hex for _ in payloads],\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:15:11.511892Z",
     "start_time": "2023-07-20T09:15:11.504665Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "CountResult(count=3374)"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "client.count(\"amazon\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Running the reverse image search\n",
    "\n",
    "As soon as we have the data indexed in Qdrant, it may already start acting as our reverse image search mechanism. Our queries no longer can be just textual, but we can freely use images to find similar items. For that, we surely need a query, and that will rarely be an image from the dataset. Let's find some different examples - for example from [Unsplash](https://unsplash.com), which is a source of freely usable images."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:15:11.584322Z",
     "start_time": "2023-07-20T09:15:11.513583Z"
    }
   },
   "outputs": [],
   "source": [
    "from io import BytesIO\n",
    "\n",
    "import base64\n",
    "\n",
    "def pillow_image_to_base64(image: Image) -> str:\n",
    "    \"\"\"\n",
    "    Convert a Pillow image to a base64 encoded string that can be used as an image\n",
    "    source in HTML.\n",
    "    :param image:\n",
    "    :return:\n",
    "    \"\"\"\n",
    "    buffered = BytesIO()\n",
    "    image.save(buffered, format=\"JPEG\")\n",
    "    img_str = base64.b64encode(buffered.getvalue()).decode(\"utf-8\")\n",
    "    return f\"data:image/jpeg;base64,{img_str}\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:15:11.614662Z",
     "start_time": "2023-07-20T09:15:11.589188Z"
    },
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table><tr><td><img src='' width=150></td><td><img src='' width=150></td><td><img src='' width=150></td><td><img src='' width=150></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.display import display, HTML\n",
    "\n",
    "import glob\n",
    "\n",
    "query_image_paths = list(glob.glob(\"./queries/*.jpg\"))\n",
    "images_html = \"\".join(\n",
    "    f\"<td><img src='{pillow_image_to_base64(Image.open(path))}' width=150></td>\"\n",
    "    for path in query_image_paths\n",
    ")\n",
    "display(HTML(f\"<table><tr>{images_html}</tr></table>\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:15:11.934081Z",
     "start_time": "2023-07-20T09:15:11.616193Z"
    },
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table><tr><td><img src='' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/51XeAj0UbGL.jpg' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/419CVufspPL.jpg' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/41W6%2B-20kwL.jpg' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/31KczNYX76L.jpg' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/41l1oid5BeL.jpg' width=150></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<table><tr><td><img src='' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/419FRcH5fGL.jpg' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/316IUgy42FL.jpg' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/51qVfIUTn4L.jpg' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/51OAmIpsKyL.jpg' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/41SWe4CCrGL.jpg' width=150></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<table><tr><td><img src='' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/31QT4VeFjFL.jpg' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/41VQkQihEfL.jpg' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/51z9yxTAo9L.jpg' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/51OcP5VO8iL.jpg' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/21rznoUHSQL.jpg' width=150></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<table><tr><td><img src='' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/41Vpz4C8vaL.jpg' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/41nykKYue9L.jpg' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/51M0TLROasL.jpg' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/51qGi36byiL.jpg' width=150></td><td><img src='https://images-na.ssl-images-amazon.com/images/I/21ZEUXz6ZLL.jpg' width=150></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "for query_image_path in query_image_paths:\n",
    "    query_image = Image.open(query_image_path)\n",
    "    query_embedding = model.encode(query_image)\n",
    "    \n",
    "    results = client.search(\n",
    "        collection_name=\"amazon\",\n",
    "        query_vector=query_embedding,\n",
    "        with_payload=True,\n",
    "        limit=5,\n",
    "    )\n",
    "    \n",
    "    output_images = [\n",
    "        pillow_image_to_base64(Image.open(query_image_path)),\n",
    "    ]\n",
    "    for result in results:\n",
    "        output_images.append(result.payload[\"Image\"])\n",
    "    \n",
    "    images_html = \"\".join(\n",
    "        f\"<td><img src='{path}' width=150></td>\"\n",
    "        for path in output_images\n",
    "    )\n",
    "    display(HTML(f\"<table><tr>{images_html}</tr></table>\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We've implemented a reverse image search mechanism for e-commerce within a single notebook. We can kill the running Docker container for now, so nothing is left dangling in our environment."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-07-20T09:15:13.850345Z",
     "start_time": "2023-07-20T09:15:11.938136Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "reverse_image_search\n",
      "reverse_image_search\n"
     ]
    }
   ],
   "source": [
    "!docker kill reverse_image_search\n",
    "!docker rm reverse_image_search"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Futher steps\n",
    "\n",
    "The notebook shows the general pipeline of encoding the inventory and using Qdrant to perform the reverse image search. There are, however, some challenges you may encounter while trying to implement it in the real world:\n",
    "\n",
    "1. Pretrained models are great to start with but may struggle for some specific kinds of inventory if not trained on similar examples. You can always fine-tune them with small amounts of data to avoid a full training cycle.\n",
    "2. Models should not be hosted within Jupyter notebooks, but there are some ways to serve them efficiently. We're going to describe the possibilities in a separate tutorial.\n",
    "3. If you don't want to worry about maintaining another system in your stack, please consider using [Qdrant Cloud](https://cloud.qdrant.io/), our managed solution. Our tier is free forever and available to everyone - no credit card is required."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
